📄 sockio.c
字号:
/* ---------------------------------------------------------------------------- CFL - A C Foundation Library Copyright (C) 1994-2003 Mark A Lindner This file is part of CFL. This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ---------------------------------------------------------------------------- $Log: sockio.c,v $ Revision 1.1 2003/03/03 08:20:08 markl Initial checkin (clean compile on Solaris & OS X) ----------------------------------------------------------------------------*//* Feature test switches */#include "config.h"/* System headers */#include <string.h>/* Local headers */#include "cfl/defs.h"#include "cfl/net.h"#include "cfl/cerrno.h"#include "cfl/system.h"#include "netcommon.h"/* Functions */int C_socket_send(c_socket_t *s, const char *buf, size_t bufsz, c_bool_t oobf) { int b; if(!s || !buf) { C_error_set_errno(C_EINVAL); return(-1); } if(s->state != C_NET_CONNECTED) { C_error_set_errno(C_EBADSTATE); return(-1); } switch(s->type) { case C_NET_TCP: { int flags = (oobf ? MSG_OOB : 0), bsofar = 0, bleft = (int)bufsz; char *p = (char *)buf; do {SEND1: b = send(s->sd, p, bleft, flags); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-bsofar); } else if(b < 0) { switch(errno) { case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(-bsofar); case EINTR: goto SEND1; default: C_error_set_errno(C_ESEND); return(-bsofar); } } else bleft -= b, bsofar += b, p += b; } while(bleft); return(bsofar); } case C_NET_UDP: { SENDTO1: b = sendto(s->sd, buf, (int)bufsz, 0, ((s->state == C_NET_CONNECTED) ? NULL : (struct sockaddr *)&(s->raddr)), ((s->state == C_NET_CONNECTED) ? 0 : (int)sizeof(struct sockaddr_in))); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(0); } else if(b < 0) { switch(errno) { case EMSGSIZE: C_error_set_errno(C_EMSG2BIG); return(-1); case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(0); case EINTR: goto SENDTO1; default: C_error_set_errno(C_ESEND); return(-1); } } else return(b); } default: C_error_set_errno(C_EBADTYPE); return(-1); } }/* */int C_socket_recv(c_socket_t *s, char *buf, size_t bufsz, c_bool_t oobf) { int b = 0; if(!s || !buf || !bufsz) { C_error_set_errno(C_EINVAL); return(-1); } if(s->state != C_NET_CONNECTED) { C_error_set_errno(C_EBADSTATE); return(-1); } switch(s->type) { case C_NET_TCP: { int flags = (oobf ? MSG_OOB : 0), bsofar = 0, bleft = (int)bufsz; char *p = buf; do {RECV1: b = recv(s->sd, p, bleft, flags); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-bsofar); } else if(b < 0) { switch(errno) { case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(-bsofar); case EINTR: goto RECV1; default: C_error_set_errno(C_ERECV); return(-bsofar); } } else bleft -= b, bsofar += b, p += b; } while(bleft); return(bsofar); } case C_NET_UDP: { int sz = (int)sizeof(struct sockaddr_in);RECVFROM1: b = recvfrom(s->sd, buf, (int)bufsz, 0, ((s->state == C_NET_CONNECTED) ? NULL : (struct sockaddr *)&(s->raddr)), ((s->state == C_NET_CONNECTED) ? NULL : &sz)); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(0); } else if(b < 0) { switch(errno) { case EMSGSIZE: C_error_set_errno(C_EMSG2BIG); return(-1); case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(0); case EINTR: goto RECVFROM1; default: C_error_set_errno(C_ERECV); return(-1); } } else return(b); } default: C_error_set_errno(C_EBADTYPE); return(-1); } }/* */int C_socket_sendto(c_socket_t *s, const char *buf, size_t bufsz, const char *addr, in_port_t port) { int b; if(!s || !buf || !bufsz) { C_error_set_errno(C_EINVAL); return(-1); } if(s->state != C_NET_CREATED) { C_error_set_errno(C_EBADSTATE); return(-1); } if(s->type != C_NET_UDP) { C_error_set_errno(C_EBADTYPE); return(-1); } if(addr) { if(! *addr) { C_error_set_errno(C_EINVAL); return(-1); } if(!__C_socket_addr2sock(&(s->raddr), addr)) { C_error_set_errno(C_EADDRINFO); return(-1); } s->raddr.sin_port = htons(port); } SENDTO2: b = sendto(s->sd, buf, (int)bufsz, 0, (struct sockaddr *)&(s->raddr), (int)sizeof(struct sockaddr_in)); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-1); } else if(b < 0) { switch(errno) { case EMSGSIZE: C_error_set_errno(C_EMSG2BIG); return(-1); case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(0); case EINTR: goto SENDTO2; default: C_error_set_errno(C_ESENDTO); return(-1); } } else return(b); }/* */int C_socket_sendreply(c_socket_t *s, const char *buf, size_t bufsz) { int b; if(!s || !buf || !bufsz) { C_error_set_errno(C_EINVAL); return(-1); } if(s->state != C_NET_CREATED) { C_error_set_errno(C_EBADSTATE); return(-1); } if(s->type != C_NET_UDP) { C_error_set_errno(C_EBADTYPE); return(-1); }SENDTO3: b = sendto(s->sd, buf, (int)bufsz, 0, (struct sockaddr *)&(s->raddr), (int)sizeof(struct sockaddr_in)); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-1); } else if(b < 0) { switch(errno) { case EMSGSIZE: C_error_set_errno(C_EMSG2BIG); return(-1); case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(0); case EINTR: goto SENDTO3; default: C_error_set_errno(C_ESENDTO); return(-1); } } else return(b); }/* */int C_socket_recvfrom(c_socket_t *s, char *buf, size_t bufsz, char *addr, size_t addrsz) { int b, sz = (int)sizeof(struct sockaddr_in); if(!s || !buf || !bufsz) { C_error_set_errno(C_EINVAL); return(-1); } if(s->state != C_NET_CREATED) { C_error_set_errno(C_EBADSTATE); return(-1); } if(s->type != C_NET_UDP) { C_error_set_errno(C_EBADTYPE); return(-1); }RECVFROM2: b = recvfrom(s->sd, buf, (int)bufsz, 0, (struct sockaddr *)&(s->raddr), &sz); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-1); } else if(b < 0) { switch(errno) { case EMSGSIZE: C_error_set_errno(C_EMSG2BIG); return(-1); case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(0); case EINTR: goto RECVFROM2; default: C_error_set_errno(C_ERECVFROM); return(-1); } } else { if(addr) { if(!addrsz) { C_error_set_errno(C_EINVAL); return(-1); } __C_socket_sock2addr(&(s->raddr), addr, addrsz); } return(b); } }/* */int C_socket_recvreply(c_socket_t *s, char *buf, size_t bufsz) { int b, sz = (int)sizeof(struct sockaddr_in); if(!s || !buf || !bufsz) { C_error_set_errno(C_EINVAL); return(-1); } if(s->state != C_NET_CREATED) { C_error_set_errno(C_EBADSTATE); return(-1); } if(s->type != C_NET_UDP) { C_error_set_errno(C_EBADTYPE); return(-1); }RECVFROM3: b = recvfrom(s->sd, buf, (int)bufsz, 0, (struct sockaddr *)&(s->raddr), &sz); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-1); } else if(b < 0) { switch(errno) { case EMSGSIZE: C_error_set_errno(C_EMSG2BIG); return(-1); case EWOULDBLOCK: C_error_set_errno(C_EBLOCKED); return(0); case EINTR: goto RECVFROM3; default: C_error_set_errno(C_ERECVFROM); return(-1); } } else return(b); }/* */static int __C_socket_write(int sd, const char *buf, size_t bufsz, uint_t slen, uint_t *snum) { char *p = (char *)buf; int bsofar = 0, bleft = (int)bufsz, b, e; struct timeval tv; fd_set fdset; FD_ZERO(&fdset); FD_SET(sd, &fdset); for(;;) {SELECT: tv.tv_usec = 0, tv.tv_sec = slen; e = select(FD_SETSIZE, NULL, &fdset, NULL, &tv); if(e == 0) { C_error_set_errno(C_ETIMEOUT); return(-bsofar); } else if(e < 0) { switch(errno) { case EINTR: goto SELECT; default: C_error_set_errno(C_ESELECT); return(-bsofar); } }SEND3: b = send(sd, p, bleft, 0); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-bsofar); } else if(b < 0) { switch(errno) { case EWOULDBLOCK: if(!(*snum)--) { C_error_set_errno(C_ETIMEOUT); return(-bsofar); } else continue; break; case EINTR: goto SEND3; default: C_error_set_errno(C_ESEND); return(-bsofar); } } else { p += b, bsofar += b; if(!(bleft -= b)) break; } } return(bsofar); }/* */static int __C_socket_read(int sd, char *buf, size_t bufsz, char termin, uint_t slen, uint_t *snum) { char *p = buf, *q; int bsofar = 0, bleft = (int)(--bufsz), i, b, e; struct timeval tv; fd_set fdset; FD_ZERO(&fdset); FD_SET(sd, &fdset); for(;;) {SELECT2: tv.tv_usec = 0, tv.tv_sec = slen; e = select(FD_SETSIZE, &fdset, NULL, NULL, &tv); if(e == 0) { C_error_set_errno(C_ETIMEOUT); return(-bsofar); } else if(e < 0) { switch(errno) { case EINTR: goto SELECT2; default: C_error_set_errno(C_ESELECT); return(-bsofar); } }RECV3: b = recv(sd, p, bleft, MSG_PEEK); if(b == 0) { C_error_set_errno(C_ELOSTCONN); return(-bsofar); } else if(b < 0) { switch(errno) { case EWOULDBLOCK: if(!(*snum)--) { C_error_set_errno(C_ETIMEOUT); return(-bsofar); } else continue; break; case EINTR: goto RECV3; default: C_error_set_errno(C_ERECV); return(-bsofar); } } else { /* try to find terminator */ for(q = p, i = 0; i < b; q++, i++) if(*q == termin) { b = bleft = i + 1; break; }RECV4: if((i = recv(sd, p, b, 0)) != b) { if((i < 0) && (errno == EINTR)) goto RECV4; C_error_set_errno(C_ERECV); return(-bsofar); } bsofar += b; if(!(bleft -= b)) break; p += b; } } *(buf + bsofar) = NUL; return(bsofar); }/* */int C_socket_writeline(c_socket_t *s, const char *buf, const char *termin, uint_t slen, uint_t snum) { int b = 0, c; if(!s || (!buf && !termin)) { C_error_set_errno(C_EINVAL); return(-1); } if(!((s->state == C_NET_CONNECTED) && !(s->flags & C_NET_MUNBLOCK) && !C_bit_isset(s->flags, C_NET_OSHUTWR))) { C_error_set_errno(C_EBADSTATE); return(-1); } if(s->type != C_NET_TCP) { C_error_set_errno(C_EBADTYPE); return(-1); } if(buf) if(*buf) if((b = __C_socket_write(s->sd, buf, strlen(buf), slen, &snum)) <= 0) return(b); if(termin) if(*termin) { if((c = __C_socket_write(s->sd, termin, strlen(termin), slen, &snum)) <= 0) return(-c + b); else b += c; } return(b); }/* */int C_socket_readline(c_socket_t *s, char *buf, size_t bufsz, char termin, uint_t slen, uint_t snum) { if(!s || !buf || !bufsz) { C_error_set_errno(C_EINVAL); return(-1); } if(!((s->state == C_NET_CONNECTED) && !(s->flags & C_NET_MUNBLOCK) && !C_bit_isset(s->flags, C_NET_OSHUTRD))) { C_error_set_errno(C_EBADSTATE); return(-1); } if(s->type != C_NET_TCP) { C_error_set_errno(C_EBADTYPE); return(-1); } return(__C_socket_read(s->sd, buf, bufsz, termin, slen, &snum)); }/* end of source file */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -