77
88#include < string.h>
99
10+ #if defined(_WIN64)
11+ #ifndef SO_UPDATE_CONNECT_CONTEXT
12+ #define SO_UPDATE_CONNECT_CONTEXT 0x7010
13+ #endif
14+ #endif
15+
1016/* ***********************************************************************/
1117
1218/* These two functions are only used in assertions. */
@@ -286,6 +292,48 @@ static PRStatus PR_CALLBACK SocketConnectContinue(
286292 }
287293 return PR_SUCCESS ;
288294
295+ #elif defined(_WIN64)
296+ if ((out_flags & PR_POLL_WRITE ) && fd->secret ->alreadyConnected ) {
297+ fd->secret ->alreadyConnected = PR_FALSE ;
298+ return PR_SUCCESS ;
299+ }
300+ // TCP Fast Open on Windows must use ConnectEx, which uses overlapped
301+ // input/output.
302+ // To get result we need to use GetOverlappedResult.
303+ if (fd->secret ->overlappedActive ) {
304+ PR_ASSERT (fd->secret ->nonblocking );
305+ PRInt32 rvSent;
306+ if (GetOverlappedResult (osfd, &fd->secret ->ol , &rvSent, FALSE ) == TRUE )
307+ {
308+ fd->secret ->overlappedActive = FALSE ;
309+ PR_LOG (_pr_io_lm, PR_LOG_MIN ,
310+ (" SocketConnectContinue GetOverlappedResult succeeded\n " ));
311+ // When ConnectEx is used, all previously set socket options and
312+ // property are not enabled and to enable them
313+ // SO_UPDATE_CONNECT_CONTEXT option need to be set.
314+ if (setsockopt ((SOCKET )osfd, SOL_SOCKET , SO_UPDATE_CONNECT_CONTEXT , NULL , 0 ) != 0 ) {
315+ err = WSAGetLastError ();
316+ PR_LOG (_pr_io_lm, PR_LOG_MIN ,
317+ (" SocketConnectContinue setting SO_UPDATE_CONNECT_CONTEXT failed %d\n " , err));
318+ _PR_MD_MAP_SETSOCKOPT_ERROR (err);
319+ return PR_FAILURE ;
320+ }
321+ return PR_SUCCESS ;
322+ } else {
323+ err = WSAGetLastError ();
324+ PR_LOG (_pr_io_lm, PR_LOG_MIN ,
325+ (" SocketConnectContinue GetOverlappedResult failed %d\n " , err));
326+ if (err != ERROR_IO_PENDING ) {
327+ _PR_MD_MAP_CONNECT_ERROR (err);
328+ fd->secret ->overlappedActive = FALSE ;
329+ return PR_FAILURE ;
330+ } else {
331+ PR_SetError (PR_IN_PROGRESS_ERROR , 0 );
332+ return PR_FAILURE ;
333+ }
334+ }
335+ }
336+
289337#elif defined(WIN32) || defined(WIN16)
290338
291339 if (out_flags & PR_POLL_EXCEPT ) {
@@ -768,6 +816,56 @@ static PRInt32 PR_CALLBACK SocketSendTo(
768816 return count;
769817}
770818
819+ #if defined(_WIN64) && defined(WIN95)
820+ static PRInt32 PR_CALLBACK SocketTCPSendTo (
821+ PRFileDesc *fd, const void *buf, PRInt32 amount,
822+ PRIntn flags, const PRNetAddr *addr, PRIntervalTime timeout)
823+ {
824+ PRInt32 temp, count;
825+ const PRNetAddr *addrp = addr;
826+ #if defined(_PR_INET6)
827+ PRNetAddr addrCopy;
828+ #endif
829+ PRThread *me = _PR_MD_CURRENT_THREAD ();
830+
831+ if (_PR_PENDING_INTERRUPT (me)) {
832+ me->flags &= ~_PR_INTERRUPT;
833+ PR_SetError (PR_PENDING_INTERRUPT_ERROR , 0 );
834+ return -1 ;
835+ }
836+ if (_PR_IO_PENDING (me)) {
837+ PR_SetError (PR_IO_PENDING_ERROR , 0 );
838+ return -1 ;
839+ }
840+
841+ PR_ASSERT (IsValidNetAddr (addr) == PR_TRUE );
842+ #if defined(_PR_INET6)
843+ if (addr->raw .family == PR_AF_INET6 ) {
844+ addrCopy = *addr;
845+ addrCopy.raw .family = AF_INET6 ;
846+ addrp = &addrCopy;
847+ }
848+ #endif
849+
850+ count = 0 ;
851+ while (amount > 0 ) {
852+ temp = _PR_MD_TCPSENDTO (fd, buf, amount, flags,
853+ addrp, PR_NETADDR_SIZE (addr), timeout);
854+ if (temp < 0 ) {
855+ count = -1 ;
856+ break ;
857+ }
858+ count += temp;
859+ if (fd->secret ->nonblocking ) {
860+ break ;
861+ }
862+ buf = (const void *) ((const char *)buf + temp);
863+ amount -= temp;
864+ }
865+ return count;
866+ }
867+ #endif
868+
771869static PRInt32 PR_CALLBACK SocketRecvFrom (PRFileDesc *fd, void *buf, PRInt32 amount,
772870PRIntn flags, PRNetAddr *addr, PRIntervalTime timeout)
773871{
@@ -1066,6 +1164,14 @@ static PRInt16 PR_CALLBACK SocketPoll(
10661164 PRFileDesc *fd, PRInt16 in_flags, PRInt16 *out_flags)
10671165{
10681166 *out_flags = 0 ;
1167+ #if defined(_WIN64)
1168+ if (in_flags & PR_POLL_WRITE ) {
1169+ if (fd->secret ->alreadyConnected ) {
1170+ out_flags = PR_POLL_WRITE ;
1171+ return PR_POLL_WRITE ;
1172+ }
1173+ }
1174+ #endif
10691175 return in_flags;
10701176} /* SocketPoll */
10711177
@@ -1090,7 +1196,11 @@ static PRIOMethods tcpMethods = {
10901196 SocketRecv,
10911197 SocketSend,
10921198 (PRRecvfromFN)_PR_InvalidInt,
1199+ #if defined(_WIN64) && defined(WIN95)
1200+ SocketTCPSendTo, // This is for fast open. We imitate Linux interface.
1201+ #else
10931202 (PRSendtoFN)_PR_InvalidInt,
1203+ #endif
10941204 SocketPoll,
10951205 SocketAcceptRead,
10961206 SocketTransmitFile,
0 commit comments