@@ -655,29 +655,76 @@ bool MCS_connect_socket(MCSocket *p_socket, struct sockaddr_in *p_addr)
655655 if (p_socket != NULL && p_socket->fd != 0 )
656656 {
657657
658- // MM-2011-07-07: Added support for binding sockets to a network interface.
659- if (MCdefaultnetworkinterface != NULL )
660- {
661- struct sockaddr_in t_bind_addr;
662- MCAutoStringRef MCdefaultnetworkinterface_string;
663- /* UNCHECKED */ MCStringCreateWithCString (MCdefaultnetworkinterface, &MCdefaultnetworkinterface_string);
664- if (!MCS_name_to_sockaddr (*MCdefaultnetworkinterface_string, t_bind_addr))
665- {
666- p_socket->error = strclone (" can't resolve network interface" );
667- p_socket->doclose ();
668- return false ;
669- }
670-
671- t_bind_addr.sin_port = 0 ;
672-
673- if (0 != bind (p_socket->fd , (struct sockaddr *)&t_bind_addr, sizeof (struct sockaddr_in )))
674- {
675- p_socket->error = strclone (" can't bind to network interface address" );
676- p_socket->doclose ();
677- return false ;
678- }
679- }
680-
658+ // check to see if a local host or port has been passed and if so, attempt to bind
659+ // if no local host has been passed then, if set, use the network interface
660+ MCAutoStringRef t_from_host;
661+ MCAutoNumberRef t_from_port;
662+ if (!MCValueIsEmpty (p_socket->from ))
663+ {
664+ if (!MCS_name_to_host_and_port (MCNameGetString (p_socket->from ), &t_from_host, &t_from_port))
665+ {
666+ p_socket->error = strclone (" error parsing the local host and port" );
667+ p_socket->doclose ();
668+ return false ;
669+ }
670+ }
671+ if (!t_from_host.IsSet () && MCdefaultnetworkinterface != NULL )
672+ {
673+ if (!MCStringCreateWithCString (MCdefaultnetworkinterface, &t_from_host))
674+ {
675+ p_socket->error = strclone (" error parsing the network interface address" );
676+ p_socket->doclose ();
677+ return false ;
678+ }
679+ }
680+
681+ if (t_from_host.IsSet () || t_from_port.IsSet ())
682+ {
683+ // the 0 defaults tell the OS to choose any avaliable host or port
684+ if (!t_from_host.IsSet ())
685+ {
686+ if (!MCStringCreateWithCString (" 0.0.0.0" , &t_from_host))
687+ {
688+ p_socket->error = strclone (" error setting the default local host" );
689+ p_socket->doclose ();
690+ return false ;
691+ }
692+ }
693+ else if (!t_from_port.IsSet ())
694+ {
695+ if (!MCNumberCreateWithUnsignedInteger (0 , &t_from_port))
696+ {
697+ p_socket->error = strclone (" error setting the default local port" );
698+ p_socket->doclose ();
699+ return false ;
700+ }
701+ }
702+
703+ struct sockaddr_in t_bind_addr;
704+ if (!MCS_host_and_port_to_sockaddr (*t_from_host, *t_from_port, t_bind_addr))
705+ {
706+ p_socket->error = strclone (" can't resolve local host and port" );
707+ p_socket->doclose ();
708+ return false ;
709+ }
710+
711+ // setting the SO_REUSEPORT option allows the same local port to be used to connect to multiple hosts
712+ int t_port_reuse = 1 ;
713+ if (setsockopt (p_socket->fd , SOL_SOCKET, SO_REUSEPORT, (const char *)&t_port_reuse, sizeof (t_port_reuse)) != 0 )
714+ {
715+ p_socket->error = strclone (" can't use the local port" );
716+ p_socket->doclose ();
717+ return false ;
718+ }
719+
720+ if (bind (p_socket->fd , (struct sockaddr *)&t_bind_addr, sizeof (struct sockaddr_in )) != 0 )
721+ {
722+ p_socket->error = strclone (" can't bind to local host and port" );
723+ p_socket->doclose ();
724+ return false ;
725+ }
726+ }
727+
681728 p_socket->setselect ();
682729
683730#if defined(_WINDOWS_DESKTOP) || defined(_WINDOWS_SERVER)
@@ -738,7 +785,7 @@ bool open_socket_resolve_callback(void *p_context, bool p_resolved, bool p_final
738785}
739786
740787// MM-2014-06-13: [[ Bug 12567 ]] Added support for specifying an end host name to verify against.
741- MCSocket *MCS_open_socket (MCNameRef name, Boolean datagram, MCObject *o, MCNameRef mess, Boolean secure, Boolean sslverify, MCStringRef sslcertfile, MCNameRef hostname)
788+ MCSocket *MCS_open_socket (MCNameRef name, MCNameRef from, Boolean datagram, MCObject *o, MCNameRef mess, Boolean secure, Boolean sslverify, MCStringRef sslcertfile, MCNameRef hostname)
742789{
743790 if (!MCS_init_sockets ())
744791 return NULL ;
@@ -775,7 +822,7 @@ MCSocket *MCS_open_socket(MCNameRef name, Boolean datagram, MCObject *o, MCNameR
775822 MCS_socket_ioctl (sock, FIONBIO, on);
776823
777824 MCSocket *s = NULL ;
778- s = (MCSocket *)new MCSocket (name, o, mess, datagram, sock, False, False,secure);
825+ s = (MCSocket *)new MCSocket (name, from, o, mess, datagram, sock, False, False,secure);
779826
780827 if (s != NULL )
781828 {
@@ -1137,7 +1184,7 @@ MCSocket *MCS_accept(uint2 port, MCObject *object, MCNameRef message, Boolean da
11371184 if (!MCNameCreateWithNativeChars (*t_port_chars, t_length, &t_portname))
11381185 return nil;
11391186
1140- return new MCSocket (*t_portname, object, message, datagram, sock, True, False, secure);
1187+ return new MCSocket (*t_portname, NULL , object, message, datagram, sock, True, False, secure);
11411188}
11421189
11431190// MM-2014-02-12: [[ SecureSocket ]] New secure socket command. If socket is not already secure, flag as secure to ensure future communications are encrypted.
@@ -1337,7 +1384,7 @@ MCSocketwrite::~MCSocketwrite()
13371384
13381385// //////////////////////////////////////////////////////////////////////////////
13391386
1340- MCSocket::MCSocket (MCNameRef n, MCObject *o, MCNameRef m, Boolean d, MCSocketHandle sock, Boolean a, Boolean s, Boolean issecure)
1387+ MCSocket::MCSocket (MCNameRef n, MCNameRef f, MCObject *o, MCNameRef m, Boolean d, MCSocketHandle sock, Boolean a, Boolean s, Boolean issecure)
13411388{
13421389 name = MCValueRetain (n);
13431390 object = o;
@@ -1366,6 +1413,7 @@ MCSocket::MCSocket(MCNameRef n, MCObject *o, MCNameRef m, Boolean d, MCSocketHan
13661413
13671414 // MM-2014-06-13: [[ Bug 12567 ]] Added support for specifying an end host name to verify against.
13681415 endhostname = MCValueRetain (kMCEmptyName );
1416+ from = MCValueRetain (f);
13691417}
13701418
13711419MCSocket::~MCSocket ()
@@ -1379,6 +1427,7 @@ MCSocket::~MCSocket()
13791427
13801428 // MM-2014-06-13: [[ Bug 12567 ]] Added support for specifying an end host name to verify against.
13811429 MCValueRelease (endhostname);
1430+ MCValueRelease (from);
13821431}
13831432
13841433void MCSocket::deletereads ()
@@ -1546,7 +1595,7 @@ void MCSocket::readsome()
15461595 if (accepting && !IO_findsocket (*t_name, index))
15471596 {
15481597 MCSocket *t_socket;
1549- t_socket = new (nothrow) MCSocket (*t_name, object, NULL , True, fd, False, True,False);
1598+ t_socket = new (nothrow) MCSocket (*t_name, NULL , object, NULL , True, fd, False, True,False);
15501599 if (t_socket != NULL )
15511600 MCSocketsAppendToSocketList (t_socket);
15521601 }
@@ -1590,7 +1639,7 @@ void MCSocket::readsome()
15901639 /* UNCHECKED */ MCStringFormat (&n, " %s:%d" , t, MCSwapInt16NetworkToHost (addr.sin_port ));
15911640 /* UNCHECKED */ MCNameCreate (*n, &t_name);
15921641 MCSocket *t_socket;
1593- t_socket = new (nothrow) MCSocket (*t_name, object, NULL , False, newfd, False, False,secure);
1642+ t_socket = new (nothrow) MCSocket (*t_name, NULL , object, NULL , False, newfd, False, False,secure);
15941643 if (t_socket != NULL )
15951644 {
15961645 MCSocketsAppendToSocketList (t_socket);
0 commit comments