📄 tcp_nt.c
字号:
/* TCP/IP receive data * Accepts: TCP/IP stream * Returns: T if success, NIL otherwise */long tcp_getdata (TCPSTREAM *stream){ int i; fd_set fds,efds; struct timeval tmo; time_t t = time (0); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpsi == INVALID_SOCKET) return NIL; (*bn) (BLOCK_TCPREAD,NIL); while (stream->ictr < 1) { /* if nothing in the buffer */ if (tcpdebug) mm_log ("Reading TCP data",TCPDEBUG); /* simple case if not a socket */ if (stream->tcpsi != stream->tcpso) while (((i = read (stream->tcpsi,stream->ibuf,BUFLEN)) < 0) && (errno == EINTR)); else { time_t tl = time (0); time_t now = tl; time_t ti = ttmo_read ? now + ttmo_read : 0; tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ /* set bit in selection vectors */ FD_SET (stream->tcpsi,&fds); FD_SET (stream->tcpsi,&efds); errno = NIL; /* initially no error */ do { /* block under timeout */ tmo.tv_sec = (long) (ti ? ti - now : 0); i = select (stream->tcpsi+1,&fds,NIL,&efds,ti ? &tmo : NIL); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && ((errno = WSAGetLastError ()) == WSAEINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == WSAEINTR)); /* success from select, read what we can */ if (i > 0) while (((i = recv (stream->tcpsi,stream->ibuf,BUFLEN,0)) == SOCKET_ERROR) && ((errno = WSAGetLastError ()) == WSAEINTR)); else if (!i) { /* timeout, ignore if told to resume */ if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl))) continue; /* otherwise punt */ if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG); return tcp_abort (stream); } } if (i <= 0) { /* error seen? */ if (tcpdebug) { char *s,tmp[MAILTMPLEN]; if (i) sprintf (s = tmp,"TCP data read I/O error %d",errno); else s = "TCP data read end of file"; mm_log (tmp,TCPDEBUG); } return tcp_abort (stream); } stream->iptr = stream->ibuf;/* point at TCP buffer */ stream->ictr = i; /* set new byte count */ if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG); } (*bn) (BLOCK_NONE,NIL); return T;}/* TCP/IP send string as record * Accepts: TCP/IP stream * string pointer * Returns: T if success else NIL */long tcp_soutr (TCPSTREAM *stream,char *string){ return tcp_sout (stream,string,(unsigned long) strlen (string));}/* TCP/IP send string * Accepts: TCP/IP stream * string pointer * byte count * Returns: T if success else NIL */long tcp_sout (TCPSTREAM *stream,char *string,unsigned long size){ int i; struct timeval tmo; fd_set fds,efds; time_t t = time (0); blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); tmo.tv_sec = ttmo_write; tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ if (stream->tcpso == INVALID_SOCKET) return NIL; (*bn) (BLOCK_TCPWRITE,NIL); while (size > 0) { /* until request satisfied */ if (tcpdebug) mm_log ("Writing to TCP",TCPDEBUG); /* simple case if not a socket */ if (stream->tcpsi != stream->tcpso) while (((i = write (stream->tcpso,string,min (size,TCPMAXSEND))) < 0) && (errno == EINTR)); else { time_t tl = time (0); /* start of request */ time_t now = tl; time_t ti = ttmo_write ? now + ttmo_write : 0; tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ /* set bit in selection vectors */ FD_SET (stream->tcpso,&fds); FD_SET(stream->tcpso,&efds); errno = NIL; /* block and write */ do { /* block under timeout */ tmo.tv_sec = (long) (ti ? ti - now : 0); i = select (stream->tcpso+1,NIL,&fds,&efds,ti ? &tmo : NIL); now = time (0); /* fake timeout if interrupt & time expired */ if ((i < 0) && ((errno = WSAGetLastError ()) == WSAEINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == WSAEINTR)); /* OK to send data? */ if (i > 0) while (((i = send (stream->tcpso,string, (int) min (size,TCPMAXSEND),0)) == SOCKET_ERROR) && ((errno = WSAGetLastError ()) == WSAEINTR)); else if (!i) { /* timeout, ignore if told to resume */ if (tmoh && (*tmoh) ((long) (now - t),(long) (now - tl))) continue; /* otherwise punt */ if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG); return tcp_abort (stream); } } if (i <= 0) { /* error seen? */ if (tcpdebug) { char tmp[MAILTMPLEN]; sprintf (tmp,"TCP write I/O error %d",errno); mm_log (tmp,TCPDEBUG); } return tcp_abort (stream); } string += i; /* how much we sent */ size -= i; /* count this size */ if (tcpdebug) mm_log ("successfully wrote to TCP",TCPDEBUG); } (*bn) (BLOCK_NONE,NIL); return T; /* all done */}/* TCP/IP close * Accepts: TCP/IP stream */void tcp_close (TCPSTREAM *stream){ tcp_abort (stream); /* nuke the sockets */ /* flush host names */ if (stream->host) fs_give ((void **) &stream->host); if (stream->remotehost) fs_give ((void **) &stream->remotehost); if (stream->localhost) fs_give ((void **) &stream->localhost); fs_give ((void **) &stream); /* flush the stream */}/* TCP/IP abort sockets * Accepts: TCP/IP stream * Returns: NIL, always */long tcp_abort (TCPSTREAM *stream){ if (stream->tcpsi != stream->tcpso) tcp_close_socket (&stream->tcpso); else stream->tcpso = INVALID_SOCKET; return tcp_close_socket (&stream->tcpsi);}/* TCP/IP abort stream * Accepts: WinSock socket * Returns: NIL, always */long tcp_close_socket (SOCKET *sock){ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); /* something to close? */ if (sock && (*sock != INVALID_SOCKET)) { (*bn) (BLOCK_TCPCLOSE,NIL); closesocket (*sock); /* WinSock socket close */ *sock = INVALID_SOCKET; (*bn) (BLOCK_NONE,NIL); wsa_sock_open--; /* drop this socket */ } /* no more open streams? */ if (wsa_initted && !wsa_sock_open) { mm_log ("Winsock cleanup",NIL); wsa_initted = 0; /* no more sockets, so... */ WSACleanup (); /* free up resources until needed */ } return NIL;}/* TCP/IP get host name * Accepts: TCP/IP stream * Returns: host name for this stream */char *tcp_host (TCPSTREAM *stream){ return stream->host; /* use tcp_remotehost() if want guarantees */}/* TCP/IP get remote host name * Accepts: TCP/IP stream * Returns: host name for this stream */char *tcp_remotehost (TCPSTREAM *stream){ if (!stream->remotehost) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); stream->remotehost = /* get socket's peer name */ ((getpeername (stream->tcpsi,sadr,&sadrlen) == SOCKET_ERROR) || (sadrlen <= 0)) ? cpystr (stream->host) : tcp_name (sadr,NIL); fs_give ((void **) &sadr); } return stream->remotehost;}/* TCP/IP return port for this stream * Accepts: TCP/IP stream * Returns: port number for this stream */unsigned long tcp_port (TCPSTREAM *stream){ return stream->port; /* return port number */}/* TCP/IP get local host name * Accepts: TCP/IP stream * Returns: local host name */char *tcp_localhost (TCPSTREAM *stream){ if (!stream->localhost) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); stream->localhost = /* get socket's name */ ((stream->port & 0xffff000) || ((getsockname (stream->tcpsi,sadr,&sadrlen) == SOCKET_ERROR) || (sadrlen <= 0))) ? cpystr (mylocalhost ()) : tcp_name (sadr,NIL); fs_give ((void **) &sadr); } return stream->localhost; /* return local host name */}/* TCP/IP get client host address (server calls only) * Returns: client host address */char *tcp_clientaddr (){ if (!myClientAddr) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if ((getpeername (0,sadr,(void *) &sadrlen) == SOCKET_ERROR) || (sadrlen <= 0)) myClientAddr = cpystr ("UNKNOWN"); else { /* get stdin's peer name */ myClientAddr = cpystr (ip_sockaddrtostring (sadr)); if (myClientPort < 0) myClientPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myClientAddr;}/* TCP/IP get client host name (server calls only) * Returns: client host name */char *tcp_clienthost (){ if (!myClientHost) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if ((getpeername (0,sadr,(void *) &sadrlen) == SOCKET_ERROR) || (sadrlen <= 0)) myClientHost = cpystr ("UNKNOWN"); else { /* get stdin's peer name */ myClientHost = tcp_name (sadr,T); if (!myClientAddr) myClientAddr = cpystr (ip_sockaddrtostring (sadr)); if (myClientPort < 0) myClientPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myClientHost;}/* TCP/IP get client port number (server calls only) * Returns: client port number */long tcp_clientport (){ if (!myClientHost && !myClientAddr) tcp_clientaddr (); return myClientPort;}/* TCP/IP get server host address (server calls only) * Returns: server host address */char *tcp_serveraddr (){ if (!myServerAddr) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (!wsa_initted++) { /* init Windows Sockets */ WSADATA wsock; if (WSAStartup (WINSOCK_VERSION,&wsock)) { wsa_initted = 0; return "random-pc"; /* try again later? */ } } if ((getsockname (0,sadr,(void *) &sadrlen) == SOCKET_ERROR) || (sadrlen <= 0)) myServerAddr = cpystr ("UNKNOWN"); else { /* get stdin's name */ myServerAddr = cpystr (ip_sockaddrtostring (sadr)); if (myServerPort < 0) myServerPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myServerAddr;}/* TCP/IP get server host name (server calls only) * Returns: server host name */char *tcp_serverhost (){ if (!myServerHost) { /* once-only */ size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); if (!wsa_initted++) { /* init Windows Sockets */ WSADATA wsock; if (WSAStartup (WINSOCK_VERSION,&wsock)) { wsa_initted = 0; return "random-pc"; /* try again later? */ } } /* get stdin's name */ if ((getsockname (0,sadr,(void *) &sadrlen) == SOCKET_ERROR) || (sadrlen <= 0)) myServerHost = cpystr (mylocalhost ()); else { /* get stdin's name */ myServerHost = tcp_name (sadr,NIL); if (!myServerAddr) myServerAddr = cpystr (ip_sockaddrtostring (sadr)); if (myServerPort < 0) myServerPort = ip_sockaddrtoport (sadr); } fs_give ((void **) &sadr); } return myServerHost;}/* TCP/IP get server port number (server calls only) * Returns: server port number */long tcp_serverport (){ if (!myServerHost && !myServerAddr) tcp_serveraddr (); return myServerPort;}/* TCP/IP return canonical form of host name * Accepts: host name * Returns: canonical form of host name */char *tcp_canonical (char *name){ char *ret,host[MAILTMPLEN]; blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); /* look like domain literal? */ if (name[0] == '[' && name[strlen (name) - 1] == ']') return name; (*bn) (BLOCK_DNSLOOKUP,NIL); if (tcpdebug) { sprintf (host,"DNS canonicalization %.80s",name); mm_log (host,TCPDEBUG); } /* get canonical name */ if (!ip_nametoaddr (name,NIL,NIL,&ret,NIL)) ret = name; (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ if (tcpdebug) mm_log ("DNS canonicalization done",TCPDEBUG); return ret;}/* TCP/IP return name from socket * Accepts: socket * verbose flag * Returns: cpystr name */char *tcp_name (struct sockaddr *sadr,long flag){ char *ret,*t,adr[MAILTMPLEN],tmp[MAILTMPLEN]; sprintf (ret = adr,"[%.80s]",ip_sockaddrtostring (sadr)); if (allowreversedns) { blocknotify_t bn = (blocknotify_t)mail_parameters(NIL,GET_BLOCKNOTIFY,NIL); if (tcpdebug) { sprintf (tmp,"Reverse DNS resolution %s",adr); mm_log (tmp,TCPDEBUG); } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ /* translate address to name */ if (t = tcp_name_valid (ip_sockaddrtoname (sadr))) { /* produce verbose form if needed */ if (flag) sprintf (ret = tmp,"%s %s",t,adr); else ret = t; } (*bn) (BLOCK_NONE,NIL); /* alarms OK now */ if (tcpdebug) mm_log ("Reverse DNS resolution done",TCPDEBUG); } return cpystr (ret);}/* Validate name * Accepts: domain name * Returns: T if valid, NIL otherwise */char *tcp_name_valid (char *s){ int c; char *ret,*tail; /* must be non-empty and not too long */ if ((ret = (s && *s) ? s : NIL) && (tail = ret + NETMAXHOST)) { /* must be alnum, dot, or hyphen */ while ((c = *s++) && (s <= tail) && (((c >= 'A') && (c <= 'Z')) || ((c >= 'a') && (c <= 'z')) || ((c >= '0') && (c <= '9')) || (c == '-') || (c == '.'))); if (c) ret = NIL; } return ret;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -