__PDPCLIB_API__ int vfprintf(FILE *stream, const char *format, va_list arg) { int ret; #if !defined(__ZVM__) stream->quickText = 0; #endif ret = vvprintf(format, arg, stream, NULL, 0); return (ret); }
static unsigned int __listen (SOCKET *self) { vvprintf("Listening for connections..."); socket_t *sock = self->data; if (listen(sock->fd, sock->backlog) == -1) return errsys("Could not listen out on socket."); return SUCCESS; }
static unsigned int __bind (SOCKET *self) { vvprintf("Binding to socket..."); socket_t *sock = self->data; if (bind(sock->fd, (struct sockaddr *)sock->srvaddrinfo, sizeof(struct sockaddr_in)) == -1) return errsys("Could not bind to socket."); return SUCCESS; }
__PDPCLIB_API__ int vsprintf(char *s, const char *format, va_list arg) { int ret; ret = vvprintf(format, arg, NULL, s, INT_MAX); if (ret >= 0) { *(s + ret) = '\0'; } return (ret); }
__PDPCLIB_API__ int vsnprintf(char *str, size_t size, const char *format, va_list ap) { int ret; ret = vvprintf(format, ap, NULL, str, size); if (ret >= 0 && size > ret) { str[ret] = '\0'; } return (ret); }
/* This definition is stupid. Think of something better */ SOCKET * NEW(socket) (SOCKET *sk, int type, int domain, int proto, char sr, unsigned int port, const char *hostname, void *ssl_ctx) { /* Object allocation */ iiprintf(SOCKET); SOCKET *s; socket_t *sock; /* Check memory */ if (!sk) { if (!(s = nalloc(sizeof(SOCKET), "socket.object"))) return NULL; if (!(sock = (socket_t *)nalloc(sizeof(socket_t), "socket.socket"))) { free(s); return NULL; } memset(sock, 0, sizeof(socket_t)); } else { s = sk; sock = sk->data; memset(sock, 0, sizeof(socket_t)); } /* All of this can be done with a macro */ sock->buffer = NULL; sock->connection_type = type; sock->domain = domain; sock->protocol = proto; sock->addrsize = sizeof(struct sockaddr); sock->bufsz = 1024; sock->opened = 0; sock->backlog = 500; sock->waittime = 5000; // 3000 microseconds sock->hostname = !hostname ? NULL : (char *)hostname; /* Check port number (clients are zero until a request is made) */ if (port < 0 || port > 65536) { /* Free allocated socket */ vvprintf("Invalid port specified."); return errnull("Invalid port specified."); } else if (!port) sock->port = 0; else sock->port = port; #if 0 /* Service check (part of struct in the future) */ fprintf(stderr, "Checking that port binds to a real service..."); if (!services[port]) sock->service = "UNKNOWN"; else sock->service = (char *)services[port]; #endif /* Set up the address data structure for use as either client or server */ sock->_class = sr; if (sock->_class == 's') { if ((sock->srvaddrinfo = (struct sockaddr_in *)nalloc(sizeof(struct sockaddr_in), "sockaddr.info")) == NULL) return errnull("Could not allocate structure specified."); /* Some type of gethosting must be done */ memset(sock->srvaddrinfo, 0, sizeof(struct sockaddr_in)); struct sockaddr_in *saa = sock->srvaddrinfo; saa->sin_family = AF_INET; saa->sin_port = htons(sock->port); /* A smart string function can decide whether or not this is IPv6 */ (&saa->sin_addr)->s_addr = htonl(INADDR_ANY); } else if (sock->_class == 'c') { /* Set up the addrinfo structure for a future client request. */ struct addrinfo *h; memset(&sock->hints, 0, sizeof(sock->hints)); h = &sock->hints; h->ai_family = sock->domain; h->ai_socktype = sock->connection_type; } #if 0 /* Show the buffer pointer... */ fprintf(stderr, "tcp socket buffer: %p (%s)\n", sock->buffer, sock->_class == 'c' ? "client" : \ sock->_class == 'd' ? "child" : "server"); #endif /* Set up an SSL context if asked. */ if (!ssl_ctx) sock->ssl_ctx = NULL; else sock->ssl_ctx = ssl_ctx; /* Finally, create a socket. */ sock->fd = socket(sock->domain, sock->connection_type, sock->protocol); sock->opened = 1; /* Set timeout, reusable bit and any other options */ struct timeval to; to.tv_sec = 2; to.tv_usec = 0; if (setsockopt(sock->fd, SOL_SOCKET, SO_REUSEADDR, &to, sizeof(to)) == -1) { // sock->free(sock); errsys("Could not reopen socket."); return NULL; } /* Set private data */ s->data = sock; /* Set the socket info as part of the object. */ s->data->urn = NULL; /* Set the URN to NULL */ /* The standard */ s->free = &__free; s->info = &__printf; /* The rest */ s->connect = &__connect; s->bind = &__bind; s->listen = &__listen; s->accept = &__accept; s->shutdown = &__shutdown; s->close = &__close; s->send = &__send; s->recv = &__recv; s->addrinfo = &__addrinfo; s->recvd = &recvd; s->parsed = &parsed; s->release = &__release; return INITIALIZED(s); }
static unsigned int __recv (SOCKET *self) { /* Initialize */ BUFFER *ff = NULL; int rcvd = 0; int rd = 0; socket_t *sock = self->data; char msg[(const int)sock->bufsz]; unsigned int ws = sock->bufsz - 1; #if 1 #define CC "child" #define SS "server" #define CL "client" char c = sock->_class; fprintf(stderr, "tcp socket buffer: %p (%s)\n", \ ff, (c=='c') ? CL : (c=='d') ? CC : SS); #endif /* Create a new fresh buffer (clean this up...) */ if (!(ff = NEW(buffer)(binary, 0))) return errstat(0, "Failed to create buffer for socket data."); #if 1 fprintf(stderr, "Current size: %d\n", ff->size(ff)); fprintf(stderr, "tcp socket buffer is now: %p (%s)\n", \ ff, (c=='c') ? CL : (c=='d') ? CC : SS); #endif sock->buffer = ff; /* Use a buffer and connection here */ switch (sock->connection_type) { case SOCK_STREAM: /* If it's -1, die. If it's less than buffer, die */ while (1) { rcvd = recv(sock->fd, &msg, ws, 0); rd += rcvd; vvprintf("rcvd %d bytes so far\n", rd); #if 0 int c = 0; for (c=0;c<(ws > rcvd ? rcvd : ws); c++) fprintf(stderr, "'%c' ", msg[c]); #endif /* Error occurred, free or reset the buffer and die */ if (rcvd == -1) return errsys("recv() error occurred"); /* End of message reached before end of buffer */ else if (rcvd < ws) { ff->append(ff, msg, rcvd); vvprintf("Finally rcvd %d bytes.", rd); vvprintf("Current buffer size: %d\n", ff->contents(ff)->size); return SUCCESS; } /* Write the entire buffer otherwise */ ff->append(ff, msg, ws); } #if 0 case SOCK_DGRAM: rcvd = recvfrom(sock->fd, msg, ws, 0, NULL, NULL); //sock->cliaddr, &sock->cliaddrlen); if (rcvd == -1) return 0; msg[rcvd] = 0; fprintf(stderr, "udp recv'd bytes: %d\n", rcvd); fprintf(stderr, "%s\n", msg); while (1) { rcvd = recvfrom(sock->fd, msg, ws, 0, NULL, NULL); fprintf(stderr, "udp recv'd bytes: %d\n", rcvd); fprintf(stderr, "%s\n", msg); if (rcvd == -1) return 0; // return false and sock->error = errno; if (rcvd < ws) break; } return 1; #endif default: fprintf(stderr, "%s\n", "Got unknown socket option."); return 0; } return SUCCESS; }
/* So you don't segfault on accident */ static SOCKET * __blank (SOCKET *self) { vvprintf("Non fatal: (accept() called on child socket)."); return NULL; }