static int expect100(void) { ne_socket *sock = ne_sock_create(); char req[BUFSIZ], buf[BUFSIZ]; ne_status status = {0}; const ne_inet_addr *ia; int success = 0; if (strcmp(ne_get_scheme(i_session), "https") == 0) { t_context("skipping for SSL server"); return SKIP; } for (ia = ne_addr_first(i_address); ia && !success; ia = ne_addr_next(i_address)) success = ne_sock_connect(sock, ia, i_port) == 0; ONN("could not connect to server", !success); sprintf(req, "PUT %sexpect100 HTTP/1.1" EOL "Host: %s" EOL "Content-Length: 100" EOL "Expect: 100-continue" EOL EOL, i_path, ne_get_server_hostport(i_session)); NE_DEBUG(NE_DBG_SOCKET, "Request:\n%s", req); ONS("sending request", ne_sock_fullwrite(sock, req, strlen(req))); switch (ne_sock_block(sock, 30)) { case NE_SOCK_TIMEOUT: ONN("timeout waiting for interim response", FAIL); break; case 0: /* no error. */ break; default: ONN("error reading from socket", FAIL); break; } ONS("reading status line", ne_sock_readline(sock, buf, BUFSIZ)); NE_DEBUG(NE_DBG_HTTP, "[status] %s", buf); ONN("parse status line", ne_parse_statusline(buf, &status)); if (status.code == 100) { char rbuf[100] = {0}; ONN("write request body", ne_sock_fullwrite(sock, rbuf, 100)); } ne_sock_close(sock); return OK; }
int full_write(ne_socket *sock, const char *data, size_t len) { int ret = ne_sock_fullwrite(sock, data, len); NE_DEBUG(NE_DBG_SOCKET, "wrote: [%.*s]\n", (int)len, data); ONV(ret, ("write failed (%d): %s", ret, ne_sock_error(sock))); return OK; }
/* Reads a request, sends a large response, reads a request, then * sends a little response. */ static int serve_large_response(ne_socket *sock, void *ud) { int n = 0; char empty[8192]; CALL(discard_request(sock)); SEND_STRING(sock, "HTTP/1.1 200 OK\r\n" "Content-Length: " RESPSTR "\r\n" "Server: BigFileServerTM\r\n" "\r\n"); memset(empty, 0, sizeof empty); for (n = 0; n < RESPSIZE/sizeof(empty); n++) { if (ne_sock_fullwrite(sock, empty, sizeof empty)) { NE_DEBUG(NE_DBG_SOCKET, "fullwrite failed\n"); return 1; } } NE_DEBUG(NE_DBG_SOCKET, "Wrote %d lots of %d\n", n, (int)sizeof empty); CALL(discard_request(sock)); SEND_STRING(sock, "HTTP/1.1 200 OK\r\n" "Connection: close\r\n\r\n"); return 0; }
int serve_sstring(ne_socket *sock, void *ud) { struct string *str = ud; NE_DEBUG(NE_DBG_SOCKET, "Serving string: [[[%.*s]]]\n", (int)str->len, str->data); ONN("write failed", ne_sock_fullwrite(sock, str->data, str->len)); return 0; }
/* echoes back lines. */ static int echo_server(ne_socket *sock, void *ud) { ssize_t ret; while ((ret = ne_sock_readline(sock, buffer, sizeof(buffer))) > 0) { NE_DEBUG(NE_DBG_SOCKET, "Line: %s", buffer); ONN("write failed", ne_sock_fullwrite(sock, buffer, ret)); NE_DEBUG(NE_DBG_SOCKET, "Wrote line.\n"); } ONN("readline failed", ret != NE_SOCK_CLOSED); return 0; }
int double_serve_sstring(ne_socket *s, void *userdata) { struct double_serve_args *args = userdata; struct string *str; CALL(discard_request(s)); CALL(discard_body(s)); str = &args->first; NE_DEBUG(NE_DBG_SOCKET, "Serving string: [[[%.*s]]]\n", (int)str->len, str->data); ONN("write failed", ne_sock_fullwrite(s, str->data, str->len)); CALL(discard_request(s)); CALL(discard_body(s)); str = &args->second; NE_DEBUG(NE_DBG_SOCKET, "Serving string: [[[%.*s]]]\n", (int)str->len, str->data); ONN("write failed", ne_sock_fullwrite(s, str->data, str->len)); return OK; }
int serve_sstring_slowly(ne_socket *sock, void *ud) { struct string *str = ud; size_t n; NE_DEBUG(NE_DBG_SOCKET, "Slowly serving string: [[[%.*s]]]\n", (int)str->len, str->data); for (n = 0; n < str->len; n++) { ONN("write failed", ne_sock_fullwrite(sock, &str->data[n], 1)); minisleep(); } return 0; }
/* harder to simulate closure cases for an SSL connection, since it * may be doing multiple read()s or write()s per ne_sock_* call. */ static int ssl_closure(void) { ne_socket *sock; ssize_t ret; CALL(begin(&sock, serve_close, NULL)); CALL(full_write(sock, "a", 1)); CALL(await_server()); do { ret = ne_sock_fullwrite(sock, "a", 1); } while (ret == 0); ONV(ret != NE_SOCK_RESET && ret != NE_SOCK_CLOSED, ("write got %" NE_FMT_SSIZE_T " not reset or closure: %s", ret, ne_sock_error(sock))); return good_close(sock); }
static int write_reset(void) { ne_socket *sock; int ret; CALL(begin(&sock, serve_reset, NULL)); CALL(full_write(sock, "a", 1)); CALL(await_server()); ret = ne_sock_fullwrite(sock, "a", 1); if (ret == 0) { ne_sock_close(sock); return SKIP; } if (ret == NE_SOCK_CLOSED) { t_warning("got EOF, failed to elicit TCP RST"); } else { ONV(ret != NE_SOCK_RESET, ("write got %d not reset: %s", ret, ne_sock_error(sock))); } return good_close(sock); }
int serve_file(ne_socket *sock, void *ud) { char buffer[BUFSIZ]; struct stat st; struct serve_file_args *args = ud; ssize_t ret; int fd; CALL(discard_request(sock)); ne_sock_fullread(sock, buffer, clength); fd = open(args->fname, O_RDONLY); if (fd < 0) { SEND_STRING(sock, "HTTP/1.0 404 File Not Found\r\n" "Content-Length: 0\r\n\r\n"); return 0; } ONN("fstat fd", fstat(fd, &st)); SEND_STRING(sock, "HTTP/1.0 200 OK\r\n"); if (args->chunks) { sprintf(buffer, "Transfer-Encoding: chunked\r\n"); } else { sprintf(buffer, "Content-Length: %" NE_FMT_OFF_T "\r\n", st.st_size); } if (args->headers) { strcat(buffer, args->headers); } strcat(buffer, "\r\n"); SEND_STRING(sock, buffer); NE_DEBUG(NE_DBG_HTTP, "Serving %s (%" NE_FMT_OFF_T " bytes).\n", args->fname, st.st_size); if (args->chunks) { char buf[1024]; while ((ret = read(fd, &buf, args->chunks)) > 0) { /* this is a small integer, cast it explicitly to avoid * warnings with printing an ssize_t. */ sprintf(buffer, "%x\r\n", (unsigned int)ret); SEND_STRING(sock, buffer); ONN("writing body", ne_sock_fullwrite(sock, buf, ret)); SEND_STRING(sock, "\r\n"); } SEND_STRING(sock, "0\r\n\r\n"); } else { while ((ret = read(fd, buffer, BUFSIZ)) > 0) { ONN("writing body", ne_sock_fullwrite(sock, buffer, ret)); } } ONN("error reading from file", ret < 0); (void) close(fd); return OK; }
ssize_t server_send(ne_socket *sock, const char *str, size_t len) { NE_DEBUG(NE_DBG_HTTP, "Sending: %.*s\n", (int)len, str); return ne_sock_fullwrite(sock, str, len); }
static int netxml_alarm_subscribe(const char *page) { int ret, port = -1, secret = -1; char buf[LARGEBUF], *s; ne_request *request; ne_sock_addr *addr; const ne_inet_addr *ai; char resp_buf[LARGEBUF]; /* Clear response buffer */ memset(resp_buf, 0, sizeof(resp_buf)); upsdebugx(2, "%s: %s", __func__, page); sock = ne_sock_create(); if (gethostname(buf, sizeof(buf)) == 0) { dstate_setinfo("driver.hostname", "%s", buf); } else { dstate_setinfo("driver.hostname", "<unknown>"); } #ifdef HAVE_NE_SOCK_CONNECT_TIMEOUT ne_sock_connect_timeout(sock, timeout); #endif ne_sock_read_timeout(sock, 1); netxml_get_page(subdriver->configure); snprintf(buf, sizeof(buf), "<?xml version=\"1.0\"?>\n"); snprintfcat(buf, sizeof(buf), "<Subscribe>\n"); snprintfcat(buf, sizeof(buf), "<Class>%s v%s</Class>\n", progname, DRIVER_VERSION); snprintfcat(buf, sizeof(buf), "<Type>connected socket</Type>\n"); snprintfcat(buf, sizeof(buf), "<HostName>%s</HostName>\n", dstate_getinfo("driver.hostname")); snprintfcat(buf, sizeof(buf), "<XMLClientParameters>\n"); snprintfcat(buf, sizeof(buf), "<ShutdownDuration>%d</ShutdownDuration>\n", shutdown_duration); if( shutdown_timer > 0 ) { snprintfcat(buf, sizeof(buf), "<ShutdownTimer>%d</ShutdownTimer>\r\n", shutdown_timer); } else { snprintfcat(buf, sizeof(buf), "<ShutdownTimer>NONE</ShutdownTimer>\n"); } snprintfcat(buf, sizeof(buf), "<AutoConfig>LOCAL</AutoConfig>\n"); snprintfcat(buf, sizeof(buf), "<OutletGroup>1</OutletGroup>\n"); snprintfcat(buf, sizeof(buf), "</XMLClientParameters>\n"); snprintfcat(buf, sizeof(buf), "<Warning></Warning>\n"); snprintfcat(buf, sizeof(buf), "</Subscribe>\n"); /* now send subscription message setting all the proper flags */ request = ne_request_create(session, "POST", page); ne_set_request_body_buffer(request, buf, strlen(buf)); /* as the NMC reply is not xml standard compliant let's parse it this way */ do { #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(timeout+1); #endif ret = ne_begin_request(request); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(0); #endif if (ret != NE_OK) { break; } ret = ne_read_response_block(request, resp_buf, sizeof(resp_buf)); if (ret == NE_OK) { ret = ne_end_request(request); } } while (ret == NE_RETRY); ne_request_destroy(request); /* due to different formats used by the various NMCs, we need to\ break up the reply in lines and parse each one separately */ for (s = strtok(resp_buf, "\r\n"); s != NULL; s = strtok(NULL, "\r\n")) { upsdebugx(2, "%s: parsing %s", __func__, s); if (!strncasecmp(s, "<Port>", 6) && (sscanf(s+6, "%u", &port) != 1)) { return NE_RETRY; } if (!strncasecmp(s, "<Secret>", 8) && (sscanf(s+8, "%u", &secret) != 1)) { return NE_RETRY; } } if ((port == -1) || (secret == -1)) { upsdebugx(2, "%s: parsing initial subcription failed", __func__); return NE_RETRY; } /* Resolve the given hostname. 'flags' must be zero. Hex * string IPv6 addresses (e.g. `::1') may be enclosed in brackets * (e.g. `[::1]'). */ addr = ne_addr_resolve(uri.host, 0); /* Returns zero if name resolution was successful, non-zero on * error. */ if (ne_addr_result(addr) != 0) { upsdebugx(2, "%s: name resolution failure on %s: %s", __func__, uri.host, ne_addr_error(addr, buf, sizeof(buf))); ne_addr_destroy(addr); return NE_RETRY; } for (ai = ne_addr_first(addr); ai != NULL; ai = ne_addr_next(addr)) { upsdebugx(2, "%s: connecting to host %s port %d", __func__, ne_iaddr_print(ai, buf, sizeof(buf)), port); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(timeout+1); #endif ret = ne_sock_connect(sock, ai, port); #ifndef HAVE_NE_SOCK_CONNECT_TIMEOUT alarm(0); #endif if (ret == NE_OK) { upsdebugx(2, "%s: connection to %s open on fd %d", __func__, uri.host, ne_sock_fd(sock)); break; } } ne_addr_destroy(addr); if (ai == NULL) { upsdebugx(2, "%s: failed to create listening socket", __func__); return NE_RETRY; } snprintf(buf, sizeof(buf), "<Subscription Identification=\"%u\"></Subscription>", secret); ret = ne_sock_fullwrite(sock, buf, strlen(buf) + 1); if (ret != NE_OK) { upsdebugx(2, "%s: send failed: %s", __func__, ne_sock_error(sock)); return NE_RETRY; } ret = ne_sock_read(sock, buf, sizeof(buf)); if (ret < 1) { upsdebugx(2, "%s: read failed: %s", __func__, ne_sock_error(sock)); return NE_RETRY; } if (strcasecmp(buf, "<Subscription Answer=\"ok\"></Subscription>")) { upsdebugx(2, "%s: subscription rejected", __func__); return NE_RETRY; } upslogx(LOG_INFO, "NSM connection to '%s' established", uri.host); return NE_OK; }