📄 tcp_unix.c
字号:
/* TCP/IP receive buffer * Accepts: TCP/IP stream * size in bytes * buffer to read into * Returns: T if success, NIL otherwise */long tcp_getbuffer (TCPSTREAM *stream,unsigned long size,char *s){ unsigned long n; /* make sure socket still alive */ if (stream->tcpsi < 0) return NIL; /* can transfer bytes from buffer? */ if (n = min (size,stream->ictr)) { memcpy (s,stream->iptr,n); /* yes, slurp as much as we can from it */ s += n; /* update pointer */ stream->iptr +=n; size -= n; /* update # of bytes to do */ stream->ictr -=n; } if (size) { 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); (*bn) (BLOCK_TCPREAD,NIL); while (size > 0) { /* until request satisfied */ time_t tl = time (0); time_t now = tl; int ti = ttmo_read ? now + ttmo_read : 0; if (tcpdebug) mm_log ("Reading TCP buffer",TCPDEBUG); 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 = 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 == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i) { /* non-timeout result from select? */ if (i > 0) /* read what we can */ while (((i = read (stream->tcpsi,s,(int) min (maxposint,size))) < 0) && (errno == EINTR)); if (i <= 0) { /* error seen? */ if (tcpdebug) { char tmp[MAILTMPLEN]; if (i) sprintf (s = tmp,"TCP buffer read I/O error %d",errno); else s = "TCP buffer read end of file"; mm_log (s,TCPDEBUG); } return tcp_abort (stream); } s += i; /* success, point at new place to write */ size -= i; /* reduce byte count */ if (tcpdebug) mm_log ("Successfully read TCP buffer",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { if (tcpdebug) mm_log ("TCP buffer read timeout",TCPDEBUG); return tcp_abort (stream); } } (*bn) (BLOCK_NONE,NIL); } *s = '\0'; /* tie off string */ return LONGT;}/* 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 < 0) return NIL; (*bn) (BLOCK_TCPREAD,NIL); while (stream->ictr < 1) { /* if nothing in the buffer */ time_t tl = time (0); /* start of request */ time_t now = tl; int ti = ttmo_read ? now + ttmo_read : 0; if (tcpdebug) mm_log ("Reading TCP data",TCPDEBUG); tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (stream->tcpsi,&fds);/* set bit in selection vectors */ FD_SET (stream->tcpsi,&efds); errno = NIL; /* initially no error */ do { /* block under timeout */ tmo.tv_sec = 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 == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i) { /* non-timeout result from select? */ /* read what we can */ if (i > 0) while (((i = read (stream->tcpsi,stream->ibuf,BUFLEN)) < 0) && (errno == EINTR)); 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 (s,TCPDEBUG); } return tcp_abort (stream); } stream->ictr = i; /* success, set new count and pointer */ stream->iptr = stream->ibuf; if (tcpdebug) mm_log ("Successfully read TCP data",TCPDEBUG); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { if (tcpdebug) mm_log ("TCP data read timeout",TCPDEBUG); return tcp_abort (stream);/* error or timeout no-continue */ } } (*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; 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->tcpso < 0) return NIL; (*bn) (BLOCK_TCPWRITE,NIL); while (size > 0) { /* until request satisfied */ time_t tl = time (0); /* start of request */ time_t now = tl; int ti = ttmo_write ? now + ttmo_write : 0; if (tcpdebug) mm_log ("Writing to TCP",TCPDEBUG); tmo.tv_usec = 0; FD_ZERO (&fds); /* initialize selection vector */ FD_ZERO (&efds); /* handle errors too */ FD_SET (stream->tcpso,&fds);/* set bit in selection vector */ FD_SET(stream->tcpso,&efds);/* set bit in error selection vector */ errno = NIL; /* block and write */ do { /* block under timeout */ tmo.tv_sec = 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 == EINTR) && ti && (ti <= now)) i = 0; } while ((i < 0) && (errno == EINTR)); if (i) { /* non-timeout result from select? */ /* write what we can */ if (i > 0) while (((i = write (stream->tcpso,string,size)) < 0) && (errno == EINTR)); 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); } /* timeout, punt unless told not to */ else if (!tmoh || !(*tmoh) (now - t,now - tl)) { if (tcpdebug) mm_log ("TCP write timeout",TCPDEBUG); return tcp_abort (stream); } } (*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 stream */ /* 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 stream * Accepts: TCP/IP stream * Returns: NIL always */long tcp_abort (TCPSTREAM *stream){ blocknotify_t bn = (blocknotify_t) mail_parameters (NIL,GET_BLOCKNOTIFY,NIL); if (stream->tcpsi >= 0) { /* no-op if no socket */ (*bn) (BLOCK_TCPCLOSE,NIL); close (stream->tcpsi); /* nuke the socket */ if (stream->tcpsi != stream->tcpso) close (stream->tcpso); stream->tcpsi = stream->tcpso = -1; } (*bn) (BLOCK_NONE,NIL); 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,(void *) &sadrlen) ? 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,(void *) &sadrlen)) ? 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 */static char *myClientAddr = NIL;char *tcp_clientaddr (){ if (!myClientAddr) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); myClientAddr = /* get stdin's peer name */ cpystr (getpeername (0,sadr,(void *) &sadrlen) ? "UNKNOWN" : ip_sockaddrtostring (sadr)); fs_give ((void **) &sadr); } return myClientAddr;}/* TCP/IP get client host name (server calls only) * Returns: client host name */static char *myClientHost = NIL;char *tcp_clienthost (){ if (!myClientHost) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); myClientHost = /* get stdin's peer name */ getpeername (0,sadr,(void *) &sadrlen) ? cpystr ("UNKNOWN") : tcp_name (sadr,T); fs_give ((void **) &sadr); } return myClientHost;}/* TCP/IP get server host address (server calls only) * Returns: server host address */static char *myServerAddr = NIL;char *tcp_serveraddr (){ if (!myServerAddr) { size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); myServerAddr = /* get stdin's peer name */ cpystr (getsockname (0,sadr,(void *) &sadrlen) ? "UNKNOWN" : ip_sockaddrtostring (sadr)); fs_give ((void **) &sadr); } return myServerAddr;}/* TCP/IP get server host name (server calls only) * Returns: server host name */static char *myServerHost = NIL;static long myServerPort = -1;char *tcp_serverhost (){ if (!myServerHost) { /* once-only */ size_t sadrlen; struct sockaddr *sadr = ip_newsockaddr (&sadrlen); /* get stdin's name */ myServerHost = (getsockname (0,sadr,(void *) &sadrlen) || ((myServerPort = ip_sockaddrtoport (sadr)) < 0)) ? cpystr (mylocalhost ()) : tcp_name (sadr,NIL); fs_give ((void **) &sadr); } return myServerHost;}/* TCP/IP get server port number (server calls only) * Returns: server port number */long tcp_serverport (){ if (!myServerHost) tcp_serverhost (); 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); void *data; /* look like domain literal? */ if (name[0] == '[' && name[strlen (name) - 1] == ']') return name; (*bn) (BLOCK_DNSLOOKUP,NIL); /* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,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_NONSENSITIVE,data); (*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); void *data; if (tcpdebug) { sprintf (tmp,"Reverse DNS resolution %s",adr); mm_log (tmp,TCPDEBUG); } (*bn) (BLOCK_DNSLOOKUP,NIL);/* quell alarms */ data = (*bn) (BLOCK_SENSITIVE,NIL); /* 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_NONSENSITIVE,data); (*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: name 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 + -