/* abort routine originally from Cftp by Dieter Baron */ int ftp_abort(Socket* fp) { char buf[4096]; #ifdef HAVE_LIBSSH if(ftp->session) /* FIXME: what? */ return 0; #endif if(!ftp_connected()) return -1; ftp_set_close_handler(); if (sock_check_pending(fp, false) == 1) { ftp_trace("There is data on the control channel, won't send ABOR\n"); /* read remaining bytes from connection */ while(fp && sock_read(fp, buf, sizeof(buf)) > 0) /* LOOP */ ; return 0; } ftp->ti.interrupted = true; ftp_err(_("Waiting for remote to finish abort...\n")); ftp_trace("--> telnet interrupt\n"); if(sock_telnet_interrupt(ftp->ctrl) != 0) ftp_err("telnet interrupt: %s\n", strerror(errno)); /* ftp_cmd("ABOR") won't work here, * we must flush data between the ABOR command and ftp_read_reply() */ sock_krb_printf(ftp->ctrl, "ABOR"); sock_printf(ftp->ctrl, "\r\n"); sock_flush(ftp->ctrl); if(ftp_get_verbosity() == vbDebug) ftp_err("--> [%s] ABOR\n", ftp->url->hostname); else ftp_trace("--> [%s] ABOR\n", ftp->url->hostname); /* read remaining bytes from connection */ while(fp && sock_read(fp, buf, sizeof(buf)) > 0) /* LOOP */ ; /* we expect a 426 or 226 reply here... */ ftp_read_reply(); if(ftp->fullcode != 426 && ftp->fullcode != 226) ftp_trace("Huh!? Expected a 426 or 226 reply\n"); /* ... and a 226 or 225 reply here, respectively */ /* FIXME: should skip this reply if prev. reply wasn't 426 or 226 ? */ ftp_read_reply(); if(ftp->fullcode != 226 && ftp->fullcode != 225) ftp_trace("Huh!? Expected a 226 or 225 reply\n"); return -1; }
static int netchar_open(struct inode* inodp, struct file* fp) { int ret; struct fop_request req; struct fop_reply rep; memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); _PKI("open...."); req.call = FOP_OPEN; req.flags = fp->f_flags; req.mode = fp->f_mode; ret = sock_write(nc_socket, &req, sizeof(req)); _PKI("sendmsg: %i", ret); ret = sock_read(nc_socket, &rep, sizeof(rep)); _PKI("recvmsg: %i", ret); _PKI("open returning %i", rep.open); return rep.open; }
uint16_t proto_receive(proto_t** p, sock_t* s) { proto_t* self = *p; uint32_t rc; if(self == NULL) { self = init(); *p = self; } while(true) { rc = sock_read(s); if(check_for_message(self, s)) return get_message_type(self); if(rc & (ASIO_ERROR | ASIO_WOULDBLOCK)) break; } return PROTO_NOP; }
static int waitreply(int res) { char result[1024]; char *ch, *str; int reply = -1; ftruncate (2, 0); lseek (2, 0, SEEK_SET); result[0] = '\0'; while (sock_ready () && sock_read (word, 512) > 1) { str = word; if (reply == -1 && (reply = (word[0] == '+'))) { if ((ch = strchr (str, '\r')) || (ch = strchr (str, '\n'))) { *ch = '\0'; snprintf (result, 1023, "### %s %d \"%s\"\n", cmd, reply, str); str = ch + (ch[1] == '\n' ? 2 : 1); } } // TODO: Fix possible \r\n issues if ((ch = strstr (str, "\r\n."))) *ch = '\0'; write (2, str, strlen (str)); } write (2, "\n", 1); if (res) { if (result[0] == '\0') snprintf (result, 1023, "### %s %d \"\"\n", cmd, reply); write (1, result, strlen (result)); } return reply; }
int recvChunk( PZ_BUF zBuf, int sockfd, int len) { int i, rlen = 0; int i_timeout; zBufSetSize(zBuf, zBuf->length + len); do { i_timeout = 10; if ((i = sock_read( sockfd, zBuf->buf+zBuf->length, len-rlen, &i_timeout)) <= 0) // if ((i = recv(sockfd, zBuf->buf+zBuf->length, len-rlen, 0)) <= 0) { return(-1); } zBuf->length += i; rlen += i; ZInfo4(DBG_MISC, "\t\tRcvd %d bytes accumulated->%d totallen->%d", i, rlen, len); } while (rlen < len && i); zBuf->buf[zBuf->length] = '\0'; ZInfo4(DBG_MISC, "\t\tExiting with len->%d", rlen); return rlen; }
int sock_read(int sock, char *buff, int bufLen, int ntimeout) { fd_set fds; int readret, selrtn; struct timeval timeout; timeout.tv_sec = ntimeout; timeout.tv_usec = 0; FD_ZERO(&fds); FD_SET(sock, &fds); selrtn = select(sock + 1, &fds, NULL, NULL, &timeout); if (selrtn < 0) { write_log("select error:[%d][%s]", errno, strerror(errno)); return -1; } if (selrtn == 0) { write_log("select timeout:[%d][%s]", errno, strerror(errno)); return 0; } return sock_read(sock, buff, bufLen); }
/* * Fill the internal buffer. If an error occurs or if the read * operation timed out -1 is returned. * @param S A Socket object * @param timeout The number of seconds to wait for data to be read * @return TRUE (the length of data read) or -1 if an error occured */ static int fill(Socket_T S, int timeout) { int n; S->offset = 0; S->length = 0; /* Optimizing, assuming a request/response pattern and that a udp_write was issued before we are called, we don't have to wait for data */ if (S->type == SOCK_DGRAM) timeout = 0; /* Read as much as we can, but only block on the first read */ while (RBUFFER_SIZE > S->length) { if (S->ssl) { n = recv_ssl_socket(S->ssl, S->buffer + S->length, RBUFFER_SIZE-S->length, timeout); } else { n = (int)sock_read(S->socket, S->buffer + S->length, RBUFFER_SIZE-S->length, timeout); } timeout = 0; if (n > 0) { S->length += n; continue; } else if (n < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || S->type == SOCK_DGRAM) break; return -1; } else break; } return S->length; }
int __mg_handle_request (int clifd, int req_id, int cli) { int n; char* buff; size_t len_data; if ((n = sock_read (clifd, &len_data, sizeof (size_t))) == SOCKERR_IO) return SOCKERR_IO; else if (n == SOCKERR_CLOSED) { goto error; } if (len_data <= sizeof (_request_data_buff)) { buff = _request_data_buff; } else { buff = malloc (len_data); if (buff == NULL) return SOCKERR_INVARG; } if ((n = sock_read (clifd, buff, len_data)) == SOCKERR_IO) return SOCKERR_IO; else if (n == SOCKERR_CLOSED) { goto error; } if (req_id > MAX_REQID || req_id <= 0 || handlers [req_id - 1] == NULL) return SOCKERR_INVARG; n = handlers [req_id - 1] (cli, clifd, buff, len_data); if (len_data > sizeof (_request_data_buff)) free (buff); if (n == SOCKERR_IO) goto error; if (req_id == REQID_IAMLIVE && mgClients [cli].has_dirty) __mg_check_dirty_znode (cli); return n; error: __mg_remove_client (cli, clifd); return SOCKERR_CLOSED; }
static ssize_t netchar_read(struct file* fp, char *buffer, size_t length, loff_t* offset) { int ret; struct fop_request req; struct fop_reply rep; void* payload = NULL; memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); _PKI("read..."); req.call = FOP_READ; req.count = length; ret = sock_write(nc_socket, &req, sizeof(req)); _PKI("sendmsg: %i", ret); ret = sock_read(nc_socket, &rep, sizeof(rep)); _PKI("recvmsg: %i", ret); _PKI("read returning %zi", rep.read); if (rep.read > 0) { payload = kmalloc(rep.read, GFP_KERNEL); if(payload == NULL){ _PKA("Read Error: kmalloc returned NULL"); return 0; } ret = sock_read(nc_socket, payload, rep.read); _PKI("payload read returned: %i", ret); ret = copy_to_user(buffer, payload, rep.read); _PKI("payload copy returned: %i", ret); kfree(payload); payload = NULL; } return rep.read; }
/* * "background" process handling echo + discard TCP sockets. */ static void echo_discard_daemon (void) { sock_type *s = (sock_type*) &tcp_echo_sock; if (sock_dataready(s)) { BYTE buf[ETH_MAX_DATA]; int len = sock_read (s, buf, sizeof(buf)); sock_write (s, buf, len); } }
/** * Wait answer from socket * * @param __maxlen - max buffer length * @param __buf - buffer to store answer */ static void lrvm_ipc_wait_answer (int __maxlen, char *__buf) { struct timespec timestruc; int trycount = read_timeout / read_delay; if (trycount <= 0) { trycount = 1; } timestruc.tv_sec = read_delay / NSEC_COUNT; timestruc.tv_nsec = read_delay % NSEC_COUNT; for (;;) { if (sock_read (sock, __maxlen, __buf) > 0) break; trycount--; if (!trycount) { /* No answer for too long. Terminate executing. */ term (); } nanosleep (×truc, 0); } if (!strncmp (__buf, "-ERR", 4)) { /* Got an error */ if (!exiting) { /* * If not already exiting, try to send bug report to * server stuff */ char buf[1024]; int i, n; exiting = 1; n = strlen (__buf); strcpy (buf, ""); for (i = 0; i < n - 4; i++) { buf[i] = __buf[i + 4]; } buf[i] = 0; lrvm_ipc_send_command ("exec_error", buf); } term (); } }
/* Reads buflen bytes into buffer until it's full. * Returns 0 on success, -1 on error */ int sock_fullread(nsocket *sock, char *buffer, int buflen) { char *pnt; /* current position within buffer */ int len; pnt = buffer; while (buflen > 0) { len = sock_read(sock, pnt, buflen); if (len < 0) return len; buflen -= len; pnt += len; } return 0; }
unsigned int ZION_CALLBACK TcpThreadFunc(void * point) { char *p = (char*)point; SOCK_HANDLE handle; SOCK_ADDR sock_addr; char read_buf[1024]; sock_init(); if(sock_str2addr(p, &sock_addr)==NULL) { printf("tcp sock_str2addr function error\n"); goto FINISH_STATE; } handle = sock_bind(&sock_addr, 0); if(handle == SOCK_INVALID_HANDLE) { printf("tcp bind function error\n"); goto ERROR_STATE; } printf("tcp %s wait for client connect....\n", p); handle = sock_accept(handle, NULL); if(handle == SOCK_INVALID_HANDLE) { printf("tcp socket_accept function error\n"); goto ERROR_STATE; } printf("tcp client connect access\n"); while(1) { memset(read_buf, 0, sizeof(read_buf)); //sock_readbuf(handle, (void*)read_buf, sizeof(read_buf)); sock_read(handle, (void*)read_buf, sizeof(read_buf)); printf("tcp client send '%s'\n", read_buf); sock_write(handle, (void*)read_buf, (int)strlen(read_buf)); } ERROR_STATE: sock_unbind(handle); FINISH_STATE: sock_final(); return 0; }
gint socks4_connect(SockInfo *sock, const gchar *hostname, gushort port) { guchar socks_req[1024]; struct hostent *hp; g_return_val_if_fail(sock != NULL, -1); g_return_val_if_fail(hostname != NULL, -1); debug_print("socks4_connect: connect to %s:%u\n", hostname, port); socks_req[0] = 4; socks_req[1] = 1; *((gushort *)(socks_req + 2)) = htons(port); /* lookup */ if ((hp = my_gethostbyname(hostname)) == NULL) { g_warning("socks4_connect: cannot lookup host: %s", hostname); return -1; } if (hp->h_length != 4) { g_warning("socks4_connect: invalid address length for host: %s", hostname); return -1; } memcpy(socks_req + 4, (guchar *)hp->h_addr, 4); /* userid (empty) */ socks_req[8] = 0; if (sock_write_all(sock, (gchar *)socks_req, 9) != 9) { g_warning("socks4_connect: SOCKS4 initial request write failed"); return -1; } if (sock_read(sock, (gchar *)socks_req, 8) != 8) { g_warning("socks4_connect: SOCKS4 response read failed"); return -1; } if (socks_req[0] != 0) { g_warning("socks4_connect: SOCKS4 response has invalid version"); return -1; } if (socks_req[1] != 90) { g_warning("socks4_connect: SOCKS4 connection to %u.%u.%u.%u:%u failed. (%u)", socks_req[4], socks_req[5], socks_req[6], socks_req[7], ntohs(*(gushort *)(socks_req + 2)), socks_req[1]); return -1; } debug_print("socks4_connect: SOCKS4 connection to %s:%u successful.\n", hostname, port); return 0; }
static void read_sensors_hddtemp(void) { Socket *s; static gchar *old = NULL; gchar buffer[1024]; gint len = 0; if ((s = sock_connect("127.0.0.1", 7634))) { while (!len) len = sock_read(s, buffer, sizeof(buffer)); sock_close(s); if (len > 2 && buffer[0] == '|' && buffer[1] == '/') { gchar **disks; int i; if (old) g_free(old); old = g_strdup("[Hard Disk Temperature]\n"); disks = g_strsplit(buffer, "\n", 0); for (i = 0; disks[i]; i++) { gchar **fields = g_strsplit(disks[i] + 1, "|", 5); /* * 0 -> /dev/hda * 1 -> FUJITSU MHV2080AH * 2 -> 41 * 3 -> C */ old = h_strdup_cprintf("\n%s (%s)=%s\302\260%s\n", old, fields[1], fields[0], fields[2], fields[3]); g_strfreev(fields); } g_strfreev(disks); } } else { g_free(old); old = NULL; } if (old) { sensors = g_strconcat(sensors, "\n", old, NULL); } }
static int FILE_recv_binary(Socket* in, FILE *out) { time_t then = time(0) - 1; time_t now; ftp_set_close_handler(); if(foo_hookf) foo_hookf(&ftp->ti); ftp->ti.begin = false; sock_clearerr_in(in); clearerr(out); char* buf = xmalloc(FTP_BUFSIZ); while (!sock_eof(in)) { if(wait_for_input() != 0) { ftp_trace("wait_for_input() returned non-zero\n"); break; } const ssize_t n = sock_read(in, buf, FTP_BUFSIZ); if (n <= 0) break; if(ftp_sigints() > 0) { ftp_trace("break due to sigint\n"); break; } if(fwrite(buf, sizeof(char), n, out) != n) break; ftp->ti.size += n; if(foo_hookf) { now = time(0); if(now > then) { foo_hookf(&ftp->ti); then = now; } } } free(buf); ftp_set_close_handler(); return maybe_abort_in(in, out); }
int SocketPeek(SocketRef const socket, uv_buf_t *const out) { if(!socket) return UV_EINVAL; if(0 == socket->rd->len) { FREE(&socket->rdmem); int rc = sock_read(socket, READ_BUFFER, socket->rd); if(UV_EAGAIN == rc) return rc; if(rc < 0) { socket->err = rc; return rc; } socket->rdmem = socket->rd->base; } *out = *socket->rd; return 0; }
/* * recieve line to zBuf.buf+zBuf.off, return line length */ int recvNextLine( int sockfd, PZ_BUF zBuf) { int len = 1; int i_timeout = 60; while ( sock_read( sockfd, zBuf->buf + zBuf->length, 1, &i_timeout)>0 && zBuf->buf[zBuf->length++] != '\n') { len++; if (zBuf->length+1 >= zBuf->capacity) zBufSetSize(zBuf, zBuf->length + BUFSIZE); } zBuf->buf[zBuf->length] = '\0'; return len; }
int32_t _connector_read(struct handler_t* h) { char* buffer; int32_t nread, nwrite, res; connector_t* con = (connector_t*)h; nwrite = connbuffer_write_len(con->read_buf); assert(nwrite >= 0); // read buffer full fail if (0 == nwrite) { printf("fd[%d] read buffer full.\n", con->h.fd); return -1; } // still full, read fail, reactor will close connector if (0 == nwrite) return -1; // read socket buffer = connbuffer_write_buffer(con->read_buf); res = sock_read(con->h.fd, buffer, nwrite); if (res < 0) { // can't read now if (ERR_EAGAIN == ERRNO || ERR_EWOULDBLOCK == ERRNO || ERR_EINTR == ERRNO) { return 0; } else { printf("fd[%d] read errno=%d\n", con->h.fd, ERRNO); return -1; } } else if (0 == res) { // printf("fd[%d] peer close\n", con->h.fd); return -1; } else { connbuffer_write_nocopy(con->read_buf, res); buffer = connbuffer_read_buffer(con->read_buf); nread = connbuffer_read_len(con->read_buf); assert(buffer && nread); res = con->read_cb(con->h.fd, buffer, nread); if (res > 0) { connbuffer_read_nocopy(con->read_buf, res); } else { return res; } } return 0; }
static ssize_t netchar_write(struct file* fp, const char *buffer, size_t length, loff_t* offset) { int ret; struct fop_request req; struct fop_reply rep; void* payload = NULL; memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); _PKI("write..."); req.call = FOP_WRITE; req.count = length; ret = sock_write(nc_socket, &req, sizeof(req)); _PKI("sendmsg: %i", ret); payload = kmalloc(length, GFP_KERNEL); if(payload == NULL){ _PKA("Write Error: kmalloc returned NULL"); return 0; } ret = copy_from_user(payload, buffer, length); _PKI("payload copy returned: %i", ret); ret = sock_write(nc_socket, payload, length); kfree(payload); payload = NULL; _PKI("write data: %i", ret); ret = sock_read(nc_socket, &rep, sizeof(rep)); _PKI("recvmsg: %i", ret); _PKI("`write returning %zi", rep.write); return rep.read; }
http_request_t * http_request (const char *url, int port) { http_request_t *req = NULL; socket_t *sock = NULL; char *buf = NULL; char *data = NULL; size_t len = 0; size_t size = 0; int rc = 0; // init sock = sock_tcp_client_new(url, port); if (NULL == sock) { return NULL; } data = (char *) malloc(sizeof(char) * MAX_REQUEST_BUFFER_SIZE); if (NULL == data) { sock_free(sock); return NULL; } // connect rc = sock_connect(sock); if (rc < 0) { sock_free(sock); return NULL; } // read while ((len = sock_read(sock, buf, MAX_REQUEST_BUFFER_SIZE)) > 0) { printf("%s\n", buf); } req = http_request_new((http_socket_t *) sock, buf); if (NULL == req) { sock_free(sock); return NULL; } sock_close(sock); return NULL; }
static int _udpcli_thread_func(void *args) { char buf[128] = "hello,world"; int ret= 0; /* in kthread_create, it blocks all signal. so open it at here */ allow_signal(SIGKILL); allow_signal(SIGTERM); if( -1 == sock_udpcli_connect_srv(udpcli_sock, "172.20.1.35", 8080) ) { printk("error: connect to server error\n"); goto out; } _udpcli_running = 1; set_current_state(TASK_INTERRUPTIBLE); while( !kthread_should_stop() && !signal_pending(current) ) { #if 0 if( -1 == sock_write(udpcli_sock, buf, sizeof(buf), NULL) ) { printk("error: cannot send message\n"); goto out; } #endif if ( 0 < (ret = sock_read(udpcli_sock, buf, sizeof(buf), NULL)) ) { printk("%s: recv len=%d %s\n", __FUNCTION__, ret, buf); }else{ printk("%s: recv error\n", __FUNCTION__); } ssleep(1); } out: _udpcli_running = 0; printk("%s: exit\n", __FUNCTION__); return 0; }
int sock_readfile_blocked(nsocket *sock, off_t length, sock_block_reader reader, void *userdata) { char buffer[BUFSIZ]; int ret; off_t done = 0; do { ret = sock_read(sock, buffer, BUFSIZ); if (ret < 0) { if (length == -1 && ret == SOCK_CLOSED) { /* Not an error condition. */ return 0; } return ret; } done += ret; sock_call_progress(done, length); (*reader)(userdata, buffer, ret); } while ((length == -1) || (done < length)); return 0; }
static int cmd_ipc (int __argc, char **__argv) { char cmd[4096], dummy[1024]; int sock=console_get_socket (); if (__argc!=2) { console_log ("Usage: ipc <ipc command>\n"); return 0; } strcpy (cmd, __argv[1]); if (!strcmp (cmd, "")) return 0; if (sock>0) { char ans[65536]; int a; if ((a=sock_answer (sock, "%s\n", cmd))) goto __fail_; if (sock_read (sock, 65536, ans)<0 || MSG_DISCONNECT (ans)) goto __fail_; console_log ("%s", ans); } else console_log ("Not connected to server.\n"); trim (cmd, dummy); if (!strcmp (dummy, "exit")) disconnect_from_server (); return 0; __fail_: disconnect_from_server (); return 0; }
STATIC mp_obj_t socket_recv(mp_obj_t self_in, mp_obj_t len_in) { mp_int_t max_len = mp_obj_get_int(len_in); vstr_t vstr; // +1 to accommodate for trailing \0 vstr_init_len(&vstr, max_len + 1); int err; mp_uint_t len = sock_read(self_in, vstr.buf, max_len, &err); if (len == MP_STREAM_ERROR) { vstr_clear(&vstr); mp_raise_OSError(err); } if (len == 0) { vstr_clear(&vstr); return mp_const_empty_bytes; } vstr.len = len; return mp_obj_new_str_from_vstr(&mp_type_bytes, &vstr); }
int vsock_fill ( vsock_t *vsock ) { int rc; if ( vsock == NULL ) { error("vsock_fill: bad argument"); return -1; } if ( vsock->ibuf == NULL ) { error("vsock_fill: buffer not allocated"); return -1; } rc = sock_read( vsock->s, vsock->ibuf, vsock->ilen, vsock->itimeout ); vsock->iptr = vsock->ibuf; if ( rc >= 0 ) vsock->icnt = rc; else vsock->icnt = 0; debug("fill buffer with %d chars ", vsock->icnt); return rc; }
int recvChunk2( FILE* file, int sockfd, int len) { int i, rlen = 0; int i_timeout; char request[1024*64]; do { i_timeout = 10; if ((i = sock_read( sockfd, request, 1024*64, &i_timeout)) <= 0) { return(-1); } rlen += i; ZInfo4(DBG_MISC, "\t\tRcvd %d bytes accumulated->%d totallen->%d", i, rlen, len); fwrite( request, 1, i, file ); } while (rlen < len && i); ZInfo4(DBG_MISC, "\t\tExiting with len->%d", rlen); return rlen; }
static int netchar_release(struct inode* inodp, struct file* fp) { int ret; struct fop_request req; struct fop_reply rep; memset(&req, 0, sizeof(req)); memset(&rep, 0, sizeof(rep)); _PKI("release..."); req.call = FOP_RELEASE; ret = sock_write(nc_socket, &req, sizeof(req)); _PKI("sendmsg: %i", ret); ret = sock_read(nc_socket, &rep, sizeof(rep)); _PKI("recvmsg: %i", ret); _PKI("release returning %i", rep.close); return rep.close; }
protocol_s* http1_alloc(intptr_t fd, http_settings_s* settings) { validate_mem(); // HTTP/1.1 should send a busy response // if there aren't enough available file descriptors. if (sock_max_capacity() - sock_uuid2fd(fd) <= HTTP_BUSY_UNLESS_HAS_FDS) goto is_busy; // get an http object from the pool http1_protocol_s* http = pool_pop(); // of malloc one if (http == NULL) http = malloc(HTTP1_PROTOCOL_SIZE); // review allocation if (http == NULL) return NULL; // we shouldn't update the `http` protocol as a struct, as this will waste // time as the whole buffer will be zeroed out when there is no need. // setup parsing state http->buffer_pos = 0; // setup protocol callbacks http->protocol = (protocol_s){ .service = HTTP1, .on_data = (void (*)(intptr_t, protocol_s*))http1_on_data, .on_close = (void (*)(protocol_s*))http1_free, }; // setup request data http->request = (http_request_s){ .metadata.max_headers = HTTP1_MAX_HEADER_COUNT, .metadata.fd = fd, .metadata.owner = http, }; // update settings http->settings = settings; http->on_request = settings->on_request; // set the timeout server_set_timeout(fd, settings->timeout); return (protocol_s*)http; is_busy: if (settings->public_folder && settings->public_folder_length) { size_t p_len = settings->public_folder_length; struct stat file_data = {}; char fname[p_len + 8 + 1]; memcpy(fname, settings->public_folder, p_len); if (settings->public_folder[p_len - 1] == '/' || settings->public_folder[p_len - 1] == '\\') p_len--; memcpy(fname + p_len, "/503.html", 9); p_len += 9; if (stat(fname, &file_data)) goto busy_no_file; // check that we have a file and not something else if (!S_ISREG(file_data.st_mode) && !S_ISLNK(file_data.st_mode)) goto busy_no_file; int file = open(fname, O_RDONLY); if (file == -1) goto busy_no_file; sock_packet_s* packet; packet = sock_checkout_packet(); memcpy(packet->buffer, "HTTP/1.1 503 Service Unavailable\r\n" "Content-Type: text/html\r\n" "Connection: close\r\n" "Content-Length: ", 94); p_len = 94 + http_ul2a(packet->buffer + 94, file_data.st_size); memcpy(packet->buffer + p_len, "\r\n\r\n", 4); p_len += 4; if (BUFFER_PACKET_SIZE - p_len > file_data.st_size) { if (read(file, packet->buffer + p_len, file_data.st_size) < 0) { close(file); sock_free_packet(packet); goto busy_no_file; } close(file); packet->length = p_len + file_data.st_size; sock_send_packet(fd, packet); } else { packet->length = p_len; sock_send_packet(fd, packet); sock_sendfile(fd, file, 0, file_data.st_size); } return NULL; } busy_no_file: sock_write(fd, "HTTP/1.1 503 Service Unavailable\r\nContent-Length: " "13\r\n\r\nServer Busy.", 68); return NULL; } /* ***************************************************************************** HTTP/1.1 protocol bare-bones implementation */ #define HTTP_BODY_CHUNK_SIZE 3072 // 4096 /* parse and call callback */ static void http1_on_data(intptr_t uuid, http1_protocol_s* protocol) { ssize_t len = 0; ssize_t result; char buff[HTTP_BODY_CHUNK_SIZE]; char* buffer; http_request_s* request = &protocol->request; for (;;) { // handle requests with no file data if (request->body_file <= 0) { // request headers parsing if (len == 0) { buffer = protocol->buffer; // make sure headers don't overflow len = sock_read(uuid, buffer + protocol->buffer_pos, HTTP1_MAX_HEADER_SIZE - protocol->buffer_pos); // update buffer read position. protocol->buffer_pos += len; } if (len <= 0) { return; } // parse headers result = http1_parse_request_headers(buffer, protocol->buffer_pos, request); // review result if (result >= 0) { // headers comeplete // mark buffer position, for HTTP pipelining protocol->buffer_pos = result; // are we done? if (request->content_length == 0 || request->body_str) { goto handle_request; } if (request->content_length > protocol->settings->max_body_size) { goto body_to_big; } // initialize or submit body data result = http1_parse_request_body(buffer + result, len - result, request); if (result >= 0) { protocol->buffer_pos += result; goto handle_request; } else if (result == -1) // parser error goto parser_error; goto parse_body; } else if (result == -1) // parser error goto parser_error; // assume incomplete (result == -2), even if wrong, we're right. len = 0; continue; } if (request->body_file > 0) { parse_body: buffer = buff; // request body parsing len = sock_read(uuid, buffer, HTTP_BODY_CHUNK_SIZE); if (len <= 0) return; result = http1_parse_request_body(buffer, len, request); if (result >= 0) { // set buffer pos for piplining support protocol->buffer_pos = result; goto handle_request; } else if (result == -1) // parser error goto parser_error; if (len < HTTP_BODY_CHUNK_SIZE) // pause parser for more data return; goto parse_body; } continue; handle_request: // review required headers / data if (request->host == NULL) goto bad_request; http_settings_s* settings = protocol->settings; // call request callback if (protocol && settings && (protocol->settings->public_folder == NULL || http_response_sendfile2(NULL, request, settings->public_folder, settings->public_folder_length, request->path, request->path_len, settings->log_static))) { protocol->on_request(request); } // clear request state http_request_clear(request); // rotate buffer for HTTP pipelining if (result >= len) { len = 0; } else { memmove(protocol->buffer, buffer + protocol->buffer_pos, len - result); len -= result; } // restart buffer position protocol->buffer_pos = 0; buffer = protocol->buffer; } // no routes lead here. fprintf(stderr, "I am lost on a deserted island, no code can reach me here :-)\n"); return; // How did we get here? parser_error: if (request->headers_count == request->metadata.max_headers) goto too_big; bad_request: /* handle generally bad requests */ { http_response_s response = http_response_init(request); response.status = 400; http_response_write_body(&response, "Bad Request", 11); http_response_finish(&response); sock_close(uuid); protocol->buffer_pos = 0; return; } too_big: /* handle oversized headers */ { http_response_s response = http_response_init(request); response.status = 431; http_response_write_body(&response, "Request Header Fields Too Large", 31); http_response_finish(&response); sock_close(uuid); protocol->buffer_pos = 0; return; body_to_big: /* handle oversized body */ { http_response_s response = http_response_init(request); response.status = 413; http_response_write_body(&response, "Payload Too Large", 17); http_response_finish(&response); sock_close(uuid); protocol->buffer_pos = 0; return; } } } /* ***************************************************************************** HTTP/1.1 listenning API implementation */ #undef http1_listen static void http1_on_init(http_settings_s* settings) { if (settings->timeout == 0) settings->timeout = 5; if (settings->max_body_size == 0) settings->max_body_size = HTTP_DEFAULT_BODY_LIMIT; if (settings->public_folder) { settings->public_folder_length = strlen(settings->public_folder); if (settings->public_folder[0] == '~' && settings->public_folder[1] == '/' && getenv("HOME")) { char* home = getenv("HOME"); size_t home_len = strlen(home); char* tmp = malloc(settings->public_folder_length + home_len + 1); memcpy(tmp, home, home_len); if (home[home_len - 1] == '/') --home_len; memcpy(tmp + home_len, settings->public_folder + 1, settings->public_folder_length); // copy also the NULL settings->public_folder = tmp; settings->private_metaflags |= 1; settings->public_folder_length = strlen(settings->public_folder); } } } static void http1_on_finish(http_settings_s* settings) { if (settings->private_metaflags & 1) free((void*)settings->public_folder); if (settings->private_metaflags & 2) free(settings); } int http1_listen(const char* port, const char* address, http_settings_s settings) { if (settings.on_request == NULL) { fprintf( stderr, "ERROR: http1_listen requires the .on_request parameter to be set\n"); exit(11); } http_settings_s* settings_copy = malloc(sizeof(*settings_copy)); *settings_copy = settings; settings_copy->private_metaflags = 2; return server_listen(.port = port, .address = address, .on_start = (void*)http1_on_init, .on_finish = (void*)http1_on_finish, .on_open = (void*)http1_alloc, .udata = settings_copy); }
int main(int argc, char *argv[]) { complex_t coord_point, julia_constant; double x_max, x_min, y_max, y_min, x_resolution, y_resolution; double divergent_limit; char file_message[160]; char filename[100]; int icount, imax_iterations; int ipixels_across, ipixels_down; int i, j, k, julia, alternate_equation; int imin, imax, jmin, jmax; int work[5]; header_t *result = NULL; /* make an integer array of size [N x M] to hold answers. */ int *in_grid_array, *out_grid_array = NULL; int numprocs; int namelen; char processor_name[MPI_MAX_PROCESSOR_NAME]; int num_colors; color_t *colors = NULL; MPI_Status status; int listener; int save_image = 0; int optval; int num_children = DEFAULT_NUM_SLAVES; int master = 1; MPI_Comm parent, *child_comm = NULL; MPI_Request *child_request = NULL; int error_code, error; char error_str[MPI_MAX_ERROR_STRING]; int length; int index; int pid; MPI_Init(&argc, &argv); MPI_Comm_size(MPI_COMM_WORLD, &numprocs); MPI_Comm_rank(MPI_COMM_WORLD, &myid); MPI_Comm_get_parent(&parent); MPI_Get_processor_name(processor_name, &namelen); pid = getpid(); if (parent == MPI_COMM_NULL) { if (numprocs > 1) { printf("Error: only one process allowed for the master.\n"); PrintUsage(); error_code = MPI_Abort(MPI_COMM_WORLD, -1); exit(error_code); } printf("Welcome to the Mandelbrot/Julia set explorer.\n"); master = 1; /* Get inputs-- region to view (must be within x/ymin to x/ymax, make sure xmax>xmin and ymax>ymin) and resolution (number of pixels along an edge, N x M, i.e. 256x256) */ read_mand_args(argc, argv, &imax_iterations, &ipixels_across, &ipixels_down, &x_min, &x_max, &y_min, &y_max, &julia, &julia_constant.real, &julia_constant.imaginary, &divergent_limit, &alternate_equation, filename, &num_colors, &use_stdin, &save_image, &num_children); check_mand_params(&imax_iterations, &ipixels_across, &ipixels_down, &x_min, &x_max, &y_min, &y_max, &divergent_limit, &num_children); if (julia == 1) /* we're doing a julia figure */ check_julia_params(&julia_constant.real, &julia_constant.imaginary); /* spawn slaves */ child_comm = (MPI_Comm*)malloc(num_children * sizeof(MPI_Comm)); child_request = (MPI_Request*)malloc(num_children * sizeof(MPI_Request)); result = (header_t*)malloc(num_children * sizeof(header_t)); if (child_comm == NULL || child_request == NULL || result == NULL) { printf("Error: unable to allocate an array of %d communicators, requests and work objects for the slaves.\n", num_children); error_code = MPI_Abort(MPI_COMM_WORLD, -1); exit(error_code); } printf("Spawning %d slaves.\n", num_children); for (i=0; i<num_children; i++) { error = MPI_Comm_spawn(argv[0], MPI_ARGV_NULL, 1, MPI_INFO_NULL, 0, MPI_COMM_WORLD, &child_comm[i], &error_code); if (error != MPI_SUCCESS) { error_str[0] = '\0'; length = MPI_MAX_ERROR_STRING; MPI_Error_string(error, error_str, &length); printf("Error: MPI_Comm_spawn failed: %s\n", error_str); error_code = MPI_Abort(MPI_COMM_WORLD, -1); exit(error_code); } } /* send out parameters */ for (i=0; i<num_children; i++) { MPI_Send(&num_colors, 1, MPI_INT, 0, 0, child_comm[i]); MPI_Send(&imax_iterations, 1, MPI_INT, 0, 0, child_comm[i]); MPI_Send(&ipixels_across, 1, MPI_INT, 0, 0, child_comm[i]); MPI_Send(&ipixels_down, 1, MPI_INT, 0, 0, child_comm[i]); MPI_Send(&divergent_limit, 1, MPI_DOUBLE, 0, 0, child_comm[i]); MPI_Send(&julia, 1, MPI_INT, 0, 0, child_comm[i]); MPI_Send(&julia_constant.real, 1, MPI_DOUBLE, 0, 0, child_comm[i]); MPI_Send(&julia_constant.imaginary, 1, MPI_DOUBLE, 0, 0, child_comm[i]); MPI_Send(&alternate_equation, 1, MPI_INT, 0, 0, child_comm[i]); } } else { master = 0; MPI_Recv(&num_colors, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&imax_iterations, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&ipixels_across, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&ipixels_down, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&divergent_limit, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&julia, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&julia_constant.real, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&julia_constant.imaginary, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&alternate_equation, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE); } if (master) { colors = malloc((num_colors+1)* sizeof(color_t)); if (colors == NULL) { MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } Make_color_array(num_colors, colors); colors[num_colors] = 0; /* add one on the top to avoid edge errors */ } /* allocate memory */ if ( (in_grid_array = (int *)calloc(ipixels_across * ipixels_down, sizeof(int))) == NULL) { printf("Memory allocation failed for data array, aborting.\n"); MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } if (master) { int istep, jstep; int i1[400], i2[400], j1[400], j2[400]; int ii, jj; struct sockaddr_in addr; int len; char line[1024], *token; if ( (out_grid_array = (int *)calloc(ipixels_across * ipixels_down, sizeof(int))) == NULL) { printf("Memory allocation failed for data array, aborting.\n"); MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } srand(getpid()); if (!use_stdin) { addr.sin_family = AF_INET; addr.sin_addr.s_addr = INADDR_ANY; addr.sin_port = htons(DEFAULT_PORT); listener = socket(AF_INET, SOCK_STREAM, 0); if (listener == -1) { printf("unable to create a listener socket.\n"); MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } if (bind(listener, &addr, sizeof(addr)) == -1) { addr.sin_port = 0; if (bind(listener, &addr, sizeof(addr)) == -1) { printf("unable to create a listener socket.\n"); MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } } if (listen(listener, 1) == -1) { printf("unable to listen.\n"); MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } len = sizeof(addr); getsockname(listener, &addr, &len); printf("%s listening on port %d\n", processor_name, ntohs(addr.sin_port)); fflush(stdout); sock = accept(listener, NULL, NULL); if (sock == -1) { printf("unable to accept a socket connection.\n"); MPI_Abort(MPI_COMM_WORLD, -1); exit(-1); } printf("accepted connection from visualization program.\n"); fflush(stdout); #ifdef HAVE_WINDOWS_H optval = 1; setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&optval, sizeof(optval)); #endif printf("sending image size to visualizer.\n"); sock_write(sock, &ipixels_across, sizeof(int)); sock_write(sock, &ipixels_down, sizeof(int)); sock_write(sock, &num_colors, sizeof(int)); sock_write(sock, &imax_iterations, sizeof(int)); } for (;;) { /* get x_min, x_max, y_min, and y_max */ if (use_stdin) { printf("input xmin ymin xmax ymax max_iter, (0 0 0 0 0 to quit):\n");fflush(stdout); fgets(line, 1024, stdin); printf("read <%s> from stdin\n", line);fflush(stdout); token = strtok(line, " \n"); x_min = atof(token); token = strtok(NULL, " \n"); y_min = atof(token); token = strtok(NULL, " \n"); x_max = atof(token); token = strtok(NULL, " \n"); y_max = atof(token); token = strtok(NULL, " \n"); imax_iterations = atoi(token); /*sscanf(line, "%g %g %g %g", &x_min, &y_min, &x_max, &y_max);*/ /*scanf("%g %g %g %g", &x_min, &y_min, &x_max, &y_max);*/ } else { printf("reading xmin,ymin,xmax,ymax.\n");fflush(stdout); sock_read(sock, &x_min, sizeof(double)); sock_read(sock, &y_min, sizeof(double)); sock_read(sock, &x_max, sizeof(double)); sock_read(sock, &y_max, sizeof(double)); sock_read(sock, &imax_iterations, sizeof(int)); } printf("x0,y0 = (%f, %f) x1,y1 = (%f,%f) max_iter = %d\n", x_min, y_min, x_max, y_max, imax_iterations);fflush(stdout); /*printf("sending the limits: (%f,%f)(%f,%f)\n", x_min, y_min, x_max, y_max);fflush(stdout);*/ /* let everyone know the limits */ for (i=0; i<num_children; i++) { MPI_Send(&x_min, 1, MPI_DOUBLE, 0, 0, child_comm[i]); MPI_Send(&x_max, 1, MPI_DOUBLE, 0, 0, child_comm[i]); MPI_Send(&y_min, 1, MPI_DOUBLE, 0, 0, child_comm[i]); MPI_Send(&y_max, 1, MPI_DOUBLE, 0, 0, child_comm[i]); MPI_Send(&imax_iterations, 1, MPI_INT, 0, 0, child_comm[i]); } /* check for the end condition */ if (x_min == x_max && y_min == y_max) { /*printf("root bailing.\n");fflush(stdout);*/ break; } /* break the work up into 400 pieces */ istep = ipixels_across / 20; jstep = ipixels_down / 20; if (istep < 1) istep = 1; if (jstep < 1) jstep = 1; k = 0; for (i=0; i<20; i++) { for (j=0; j<20; j++) { i1[k] = MIN(istep * i, ipixels_across - 1); i2[k] = MIN((istep * (i+1)) - 1, ipixels_across - 1); j1[k] = MIN(jstep * j, ipixels_down - 1); j2[k] = MIN((jstep * (j+1)) - 1, ipixels_down - 1); k++; } } /* shuffle the work */ for (i=0; i<500; i++) { ii = rand() % 400; jj = rand() % 400; swap(&i1[ii], &i1[jj]); swap(&i2[ii], &i2[jj]); swap(&j1[ii], &j1[jj]); swap(&j2[ii], &j2[jj]); } /* send a piece of work to each worker (there must be more work than workers) */ k = 0; for (i=0; i<num_children; i++) { work[0] = k+1; work[1] = i1[k]; /* imin */ work[2] = i2[k]; /* imax */ work[3] = j1[k]; /* jmin */ work[4] = j2[k]; /* jmax */ /*printf("sending work(%d) to %d\n", k+1, i);fflush(stdout);*/ MPI_Send(work, 5, MPI_INT, 0, 100, child_comm[i]); MPI_Irecv(&result[i], 5, MPI_INT, 0, 200, child_comm[i], &child_request[i]); k++; } /* receive the results and hand out more work until the image is complete */ while (k<400) { MPI_Waitany(num_children, child_request, &index, &status); memcpy(work, &result[index], 5 * sizeof(int)); /*printf("master receiving data in k<400 loop.\n");fflush(stdout);*/ MPI_Recv(in_grid_array, (work[2] + 1 - work[1]) * (work[4] + 1 - work[3]), MPI_INT, 0, 201, child_comm[index], &status); /* draw data */ output_data(in_grid_array, &work[1], out_grid_array, ipixels_across, ipixels_down); work[0] = k+1; work[1] = i1[k]; work[2] = i2[k]; work[3] = j1[k]; work[4] = j2[k]; /*printf("sending work(%d) to %d\n", k+1, index);fflush(stdout);*/ MPI_Send(work, 5, MPI_INT, 0, 100, child_comm[index]); MPI_Irecv(&result[index], 5, MPI_INT, 0, 200, child_comm[index], &child_request[index]); k++; } /* receive the last pieces of work */ /* and tell everyone to stop */ for (i=0; i<num_children; i++) { MPI_Wait(&child_request[i], &status); memcpy(work, &result[i], 5 * sizeof(int)); /*printf("master receiving data in tail loop.\n");fflush(stdout);*/ MPI_Recv(in_grid_array, (work[2] + 1 - work[1]) * (work[4] + 1 - work[3]), MPI_INT, 0, 201, child_comm[i], &status); /* draw data */ output_data(in_grid_array, &work[1], out_grid_array, ipixels_across, ipixels_down); work[0] = 0; work[1] = 0; work[2] = 0; work[3] = 0; work[4] = 0; /*printf("sending %d to tell %d to stop\n", work[0], i);fflush(stdout);*/ MPI_Send(work, 5, MPI_INT, 0, 100, child_comm[i]); } /* tell the visualizer the image is done */ if (!use_stdin) { work[0] = 0; work[1] = 0; work[2] = 0; work[3] = 0; sock_write(sock, work, 4 * sizeof(int)); } } } else { for (;;) { /*printf("slave[%d] receiveing bounds.\n", pid);fflush(stdout);*/ MPI_Recv(&x_min, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&x_max, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&y_min, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&y_max, 1, MPI_DOUBLE, 0, 0, parent, MPI_STATUS_IGNORE); MPI_Recv(&imax_iterations, 1, MPI_INT, 0, 0, parent, MPI_STATUS_IGNORE); /*printf("slave[%d] received bounding box: (%f,%f)(%f,%f)\n", pid, x_min, y_min, x_max, y_max);fflush(stdout);*/ /* check for the end condition */ if (x_min == x_max && y_min == y_max) { /*printf("slave[%d] done.\n", pid);fflush(stdout);*/ break; } x_resolution = (x_max-x_min)/ ((double)ipixels_across); y_resolution = (y_max-y_min)/ ((double)ipixels_down); MPI_Recv(work, 5, MPI_INT, 0, 100, parent, &status); /*printf("slave[%d] received work: %d, (%d,%d)(%d,%d)\n", pid, work[0], work[1], work[2], work[3], work[4]);fflush(stdout);*/ while (work[0] != 0) { imin = work[1]; imax = work[2]; jmin = work[3]; jmax = work[4]; k = 0; for (j=jmin; j<=jmax; ++j) { coord_point.imaginary = y_max - j*y_resolution; /* go top to bottom */ for (i=imin; i<=imax; ++i) { /* Call Mandelbrot routine for each code, fill array with number of iterations. */ coord_point.real = x_min + i*x_resolution; /* go left to right */ if (julia == 1) { /* doing Julia set */ /* julia eq: z = z^2 + c, z_0 = grid coordinate, c = constant */ icount = single_mandelbrot_point(coord_point, julia_constant, imax_iterations, divergent_limit); } else if (alternate_equation == 1) { /* doing experimental form 1 */ icount = subtractive_mandelbrot_point(coord_point, julia_constant, imax_iterations, divergent_limit); } else if (alternate_equation == 2) { /* doing experimental form 2 */ icount = additive_mandelbrot_point(coord_point, julia_constant, imax_iterations, divergent_limit); } else { /* default to doing Mandelbrot set */ /* mandelbrot eq: z = z^2 + c, z_0 = c, c = grid coordinate */ icount = single_mandelbrot_point(coord_point, coord_point, imax_iterations, divergent_limit); } in_grid_array[k] = icount; ++k; } } /* send the result to the root */ /*printf("slave[%d] sending work %d back.\n", pid, work[0]);fflush(stdout);*/ MPI_Send(work, 5, MPI_INT, 0, 200, parent); /*printf("slave[%d] sending work %d data.\n", pid, work[0]);fflush(stdout);*/ MPI_Send(in_grid_array, (work[2] + 1 - work[1]) * (work[4] + 1 - work[3]), MPI_INT, 0, 201, parent); /* get the next piece of work */ /*printf("slave[%d] receiving new work.\n", pid);fflush(stdout);*/ MPI_Recv(work, 5, MPI_INT, 0, 100, parent, &status); /*printf("slave[%d] received work: %d, (%d,%d)(%d,%d)\n", pid, work[0], work[1], work[2], work[3], work[4]);fflush(stdout);*/ } } } if (master && save_image) { imax_iterations = 0; for (i=0; i<ipixels_across * ipixels_down; ++i) { /* look for "brightest" pixel value, for image use */ if (out_grid_array[i] > imax_iterations) imax_iterations = out_grid_array[i]; } if (julia == 0) printf("Done calculating mandelbrot, now creating file\n"); else printf("Done calculating julia, now creating file\n"); fflush(stdout); /* Print out the array in some appropriate form. */ if (julia == 0) { /* it's a mandelbrot */ sprintf(file_message, "Mandelbrot over (%lf-%lf,%lf-%lf), size %d x %d", x_min, x_max, y_min, y_max, ipixels_across, ipixels_down); } else { /* it's a julia */ sprintf(file_message, "Julia over (%lf-%lf,%lf-%lf), size %d x %d, center (%lf, %lf)", x_min, x_max, y_min, y_max, ipixels_across, ipixels_down, julia_constant.real, julia_constant.imaginary); } dumpimage(filename, out_grid_array, ipixels_across, ipixels_down, imax_iterations, file_message, num_colors, colors); } if (master) { for (i=0; i<num_children; i++) { MPI_Comm_disconnect(&child_comm[i]); } free(child_comm); free(child_request); free(colors); } MPI_Finalize(); return 0; }