Tcl UDP

Check-in [1a3e75af20]
Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2019 Conference, Houston/TX, US, Nov 4-8
Send your abstracts to [email protected]
or submit via the online form by Sep 9.

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment: * generic/udp_tcl.c: Applied patch 1693037 from Uwe Klein to enable setting the SO_REUSEADDR socket option when creating a new udp socket. Improved error reporting on Windows.
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 1a3e75af2042e200c41c190050336d3f281618df
User & Date: patthoyts 2007-04-10 12:25:57
Context
2007-04-10
23:36
Use winsock2 so that mingw-gcc can get the correct values for multicast. check-in: 7f3b9d24cd user: patthoyts tags: trunk
12:25
* generic/udp_tcl.c: Applied patch 1693037 from Uwe Klein to enable setting the SO_REUSEADDR socket option when creating a new udp socket. Improved error reporting on Windows. check-in: 1a3e75af20 user: patthoyts tags: trunk
2007-03-30
21:22
Upgraded TEA to 3.6 and update the version to 1.0.9. Regenerated configure. Improved the error reporting by making use of strerror() if present. check-in: 3c1551e84a user: patthoyts tags: trunk
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to ChangeLog.








1
2
3
4
5
6
7






2007-03-30  Pat Thoyts  <[email protected]>

	* generic/udp_tcl.c: Added support for IP_MULTICAST_LOOP for
	Konstantin Khomoutov to control multicast loopback transmission.
	Improved the error reporting by using strerror if available.
	* Makefile.in: Fix 'make shell' to load the built library.
	* configure.in: Incremented version and use TEA 3.6
>
>
>
>
>
>
>







1
2
3
4
5
6
7
8
9
10
11
12
13
14
2007-04-10  Pat Thoyts  <[email protected]>

	* generic/udp_tcl.c: Applied patch 1693037 from Uwe Klein to
	enable setting the SO_REUSEADDR socket option when creating a new
	udp socket.
	Improved error reporting on Windows.

2007-03-30  Pat Thoyts  <[email protected]>

	* generic/udp_tcl.c: Added support for IP_MULTICAST_LOOP for
	Konstantin Khomoutov to control multicast loopback transmission.
	Improved the error reporting by using strerror if available.
	* Makefile.in: Fix 'make shell' to load the built library.
	* configure.in: Incremented version and use TEA 3.6

Changes to Makefile.in.

8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: Makefile.in,v 1.8 2007/03/30 21:22:54 patthoyts Exp $

#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
# have been added in a customized configure script.
#========================================================================

#SAMPLE_NEW_VAR	= @[email protected]
................................................................................
	    $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
	done

test: binaries libraries
	$(TCLSH) `@[email protected] $(srcdir)/tests/all.tcl` $(TESTFLAGS)

shell: binaries libraries
	echo "load $(PKG_LIB_FILE);set argv $(SCRIPT)" | $(TCLSH)

gdb:
	$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)

depend:

#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above.  That will ensure that this target is built when you
# run "make binaries".






|







 







|


|







8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
...
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
#
# Copyright (c) 1999 Scriptics Corporation.
# Copyright (c) 2002-2005 ActiveState Corporation.
#
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
# RCS: @(#) $Id: Makefile.in,v 1.9 2007/04/10 12:25:57 patthoyts Exp $

#========================================================================
# Add additional lines to handle any additional AC_SUBST cases that
# have been added in a customized configure script.
#========================================================================

#SAMPLE_NEW_VAR	= @[email protected]
................................................................................
	    $(INSTALL_DATA) $$i $(DESTDIR)$(mandir)/mann ; \
	done

test: binaries libraries
	$(TCLSH) `@[email protected] $(srcdir)/tests/all.tcl` $(TESTFLAGS)

shell: binaries libraries
	@$(TCLSH) $(SCRIPT)

gdb:
	@$(TCLSH_ENV) gdb $(TCLSH_PROG) $(SCRIPT)

depend:

#========================================================================
# $(PKG_LIB_FILE) should be listed as part of the BINARIES variable
# mentioned above.  That will ensure that this target is built when you
# run "make binaries".

Changes to generic/udp_tcl.c.

3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
233
234
235
236
237
238
239

240
241
242
243
244
245
246
247
248




249
250
251
252
253
254
255
...
285
286
287
288
289
290
291
292
293
294
295
296
297








298
299
300
301
302
303
304
....
1454
1455
1456
1457
1458
1459
1460















1461
1462
1463
1464
1465
1466
1467
1468
1469
1470
....
1507
1508
1509
1510
1511
1512
1513
1514
1515
1516
1517
1518
1519
1520
1521
 *
 * Copyright (c) 1999-2000 by Columbia University; all rights reserved
 * Copyright (c) 2003-2005 Pat Thoyts <[email protected]>
 *
 * Written by Xiaotao Wu
 * Last modified: 11/03/2000
 *
 * $Id: udp_tcl.c,v 1.37 2007/03/30 21:22:54 patthoyts Exp $
 ******************************************************************************/

#if defined(_DEBUG) && !defined(DEBUG)
#define DEBUG
#endif

#include "udp_tcl.h"
................................................................................
udpOpen(ClientData clientData, Tcl_Interp *interp,
        int argc, CONST84 char * argv[]) 
{
    int sock;
    char channelName[20];
    UdpState *statePtr;
    uint16_t localport = 0;

#ifdef SIPC_IPV6
    struct sockaddr_in6  addr, sockaddr;
#else
    struct sockaddr_in  addr, sockaddr;
#endif
    unsigned long status = 1;
    socklen_t len;
    
    if (argc >= 2) {




        if (udpGetService(interp, argv[1], &localport) != TCL_OK)
            return TCL_ERROR;
    }
    
    memset(channelName, 0, sizeof(channelName));
    
#ifdef SIPC_IPV6
................................................................................
    addr.sin6_family = AF_INET6;
    addr.sin6_port = localport;
#else
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = 0;
    addr.sin_port = localport;
#endif
    if (bind(sock,(struct sockaddr *)&addr, sizeof(addr)) < 0) {
        snprintf(errBuf, 255, "failed to bind socket to port %u",
            ntohs(localport));
        errBuf[255] = 0;
        UDPTRACE("%s\n");
        Tcl_AppendResult(interp, errBuf, (char *)NULL);








        return TCL_ERROR;
    }

    ioctlsocket(sock, FIONBIO, &status);

    if (localport == 0) {
        len = sizeof(sockaddr);
................................................................................

    return r;
}

static Tcl_Obj *
ErrorToObj(const char * prefix)
{















    extern int errno;
    Tcl_Obj *errObj = Tcl_NewStringObj(prefix, -1);
#ifdef HAVE_STRERROR
    Tcl_AppendStringsToObj(errObj, ": ", strerror(errno), NULL);
#endif
    return errObj;
}

/*
 * ----------------------------------------------------------------------
................................................................................

static int
udpGetService(Tcl_Interp *interp, const char *service,
              unsigned short *servicePort)
{
    int port = 0;
    int r = UdpSockGetPort(interp, service, "udp", &port);
    *servicePort = htons(port);
    return r;
}

/*
 *---------------------------------------------------------------------------
 *
 * UdpSockGetPort --






|







 







>









>
>
>
>







 







|
|
|
|
|
|
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>


<







 







|







3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
...
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
...
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
....
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490

1491
1492
1493
1494
1495
1496
1497
....
1534
1535
1536
1537
1538
1539
1540
1541
1542
1543
1544
1545
1546
1547
1548
 *
 * Copyright (c) 1999-2000 by Columbia University; all rights reserved
 * Copyright (c) 2003-2005 Pat Thoyts <[email protected]>
 *
 * Written by Xiaotao Wu
 * Last modified: 11/03/2000
 *
 * $Id: udp_tcl.c,v 1.38 2007/04/10 12:25:57 patthoyts Exp $
 ******************************************************************************/

#if defined(_DEBUG) && !defined(DEBUG)
#define DEBUG
#endif

#include "udp_tcl.h"
................................................................................
udpOpen(ClientData clientData, Tcl_Interp *interp,
        int argc, CONST84 char * argv[]) 
{
    int sock;
    char channelName[20];
    UdpState *statePtr;
    uint16_t localport = 0;
    int reuse = 0;
#ifdef SIPC_IPV6
    struct sockaddr_in6  addr, sockaddr;
#else
    struct sockaddr_in  addr, sockaddr;
#endif
    unsigned long status = 1;
    socklen_t len;
    
    if (argc >= 2) {
        if ((argc >= 3) && (0 == strncmp("reuse", argv[2], 6))) {
            fprintf(stderr,"sock reuse!\n");
            reuse = 1;
        }
        if (udpGetService(interp, argv[1], &localport) != TCL_OK)
            return TCL_ERROR;
    }
    
    memset(channelName, 0, sizeof(channelName));
    
#ifdef SIPC_IPV6
................................................................................
    addr.sin6_family = AF_INET6;
    addr.sin6_port = localport;
#else
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = 0;
    addr.sin_port = localport;
#endif
    if (reuse) {
        int one = 1;
        if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
                       (const char *)&one, sizeof(one)) < 0) {
            Tcl_SetObjResult(interp, 
                             ErrorToObj("error setting socket option"));
            closesocket(sock);
            return TCL_ERROR;
        }
    }
    if (bind(sock,(struct sockaddr *)&addr, sizeof(addr)) < 0) {
        Tcl_SetObjResult(interp, 
                         ErrorToObj("failed to bind socket to port"));
        closesocket(sock);
        return TCL_ERROR;
    }

    ioctlsocket(sock, FIONBIO, &status);

    if (localport == 0) {
        len = sizeof(sockaddr);
................................................................................

    return r;
}

static Tcl_Obj *
ErrorToObj(const char * prefix)
{
    Tcl_Obj *errObj;
#ifdef WIN32
    LPVOID sMsg;
    DWORD len = 0;
    len = FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER
                         | FORMAT_MESSAGE_FROM_SYSTEM
                         | FORMAT_MESSAGE_IGNORE_INSERTS,
                         NULL, GetLastError(),
                         MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                         (LPWSTR)&sMsg, 0, NULL);
    errObj = Tcl_NewStringObj(prefix, -1);
    Tcl_AppendToObj(errObj, ": ", -1);
    Tcl_AppendUnicodeToObj(errObj, (LPWSTR)sMsg, len - 1);
    LocalFree(sMsg);
#elif defined(HAVE_STRERROR)
    extern int errno;
    Tcl_Obj *errObj = Tcl_NewStringObj(prefix, -1);

    Tcl_AppendStringsToObj(errObj, ": ", strerror(errno), NULL);
#endif
    return errObj;
}

/*
 * ----------------------------------------------------------------------
................................................................................

static int
udpGetService(Tcl_Interp *interp, const char *service,
              unsigned short *servicePort)
{
    int port = 0;
    int r = UdpSockGetPort(interp, service, "udp", &port);
    *servicePort = htons((short)port);
    return r;
}

/*
 *---------------------------------------------------------------------------
 *
 * UdpSockGetPort --

Changes to win/makefile.vc.

14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2001 ActiveState Corporation.
# Copyright (c) 2001-2002 David Gravereaux.
# Copyright (c) 2003 Pat Thoyts
#
#-------------------------------------------------------------------------
# RCS: @(#)$Id: makefile.vc,v 1.5 2005/11/27 21:32:01 patthoyts Exp $
#-------------------------------------------------------------------------

!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCToolkitInstallDir)
MSG = ^
You will need to run vcvars32.bat from Developer Studio, first, to setup^
the environment.  Jump to this line to read the new instructions.
!error $(MSG)
................................................................................
# binary here.
#
#-------------------------------------------------------------------------

PROJECT = udp
!include "rules.vc"

DOTVERSION      = 1.0.8
VERSION         = $(DOTVERSION:.=)
STUBPREFIX      = $(PROJECT)stub

DLLOBJS = \
	$(TMP_DIR)\udp_tcl.obj \
	$(TMP_DIR)\tcludp.res







|







 







|







14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
...
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
# Copyright (c) 1995-1996 Sun Microsystems, Inc.
# Copyright (c) 1998-2000 Ajuba Solutions.
# Copyright (c) 2001 ActiveState Corporation.
# Copyright (c) 2001-2002 David Gravereaux.
# Copyright (c) 2003 Pat Thoyts
#
#-------------------------------------------------------------------------
# RCS: @(#)$Id: makefile.vc,v 1.6 2007/04/10 12:25:57 patthoyts Exp $
#-------------------------------------------------------------------------

!if !defined(MSDEVDIR) && !defined(MSVCDIR) && !defined(VCToolkitInstallDir)
MSG = ^
You will need to run vcvars32.bat from Developer Studio, first, to setup^
the environment.  Jump to this line to read the new instructions.
!error $(MSG)
................................................................................
# binary here.
#
#-------------------------------------------------------------------------

PROJECT = udp
!include "rules.vc"

DOTVERSION      = 1.0.9
VERSION         = $(DOTVERSION:.=)
STUBPREFIX      = $(PROJECT)stub

DLLOBJS = \
	$(TMP_DIR)\udp_tcl.obj \
	$(TMP_DIR)\tcludp.res