TEST(Utils, UriCoding) { string src1 = "This is a simple & short test."; string src2 = "$ & < > ? ; # : = , \" ' ~ + %-_"; string src3 = "! * ' ( ) ; : @ & = + $ , / ? % # [ ]"; string src4 = "A B C D E F G H I J K L M N O P Q R S T U V W X Y Z a b c d e f g h i " "j k l m n o p q r s t u v w x y z 0 1 2 3 4 5 6 7 8 9 - _ . ~"; string dst1 = "This%20is%20a%20simple%20%26%20short%20test."; string dst2 = "%24%20%26%20%3C%20%3E%20%3F%20%3B%20%23%20%3A%20%3D%20%2C%20%22%20%27%" "20~%20%2B%20%25-_"; string dst3 = "%21%20%2A%20%27%20%28%20%29%20%3B%20%3A%20%40%20%26%20%3D%20%2B%20%24%" "20%2C%20%2F%20%3F%20%25%20%23%20%5B%20%5D"; string dst4 = "A%20B%20C%20D%20E%20F%20G%20H%20I%20J%20K%20L%20M%20N%20O%20P%20Q%20R%" "20S%20T%20U%20V%20W%20X%20Y%20Z%20a%20b%20c%20d%20e%20f%20g%20h%20i%" "20j%20k%20l%20m%20n%20o%20p%20q%20r%20s%20t%20u%20v%20w%20x%20y%20z%" "200%201%202%203%204%205%206%207%208%209%20-%20_%20.%20~"; EXPECT_STREQ(dst1.c_str(), uri_encode(src1).c_str()); EXPECT_STREQ(dst2.c_str(), uri_encode(src2).c_str()); EXPECT_STREQ(dst3.c_str(), uri_encode(src3).c_str()); EXPECT_STREQ(dst4.c_str(), uri_encode(src4).c_str()); EXPECT_STREQ(src1.c_str(), uri_decode(dst1).c_str()); EXPECT_STREQ(src2.c_str(), uri_decode(dst2).c_str()); EXPECT_STREQ(src3.c_str(), uri_decode(dst3).c_str()); EXPECT_STREQ(src4.c_str(), uri_decode(dst4).c_str()); }
static int normalize_uri(char **out, const char *uri, const struct uri *luri) { struct uri uri2; struct pl pl; int err; if (!out || !uri || !luri) return EINVAL; pl_set_str(&pl, uri); if (0 == uri_decode(&uri2, &pl)) { err = str_dup(out, uri); } else { uri2 = *luri; uri2.user = pl; uri2.password = pl_null; uri2.params = pl_null; err = re_sdprintf(out, "%H", uri_encode, &uri2); } return err; }
/** * Send a SIP request with formatted arguments * * @param reqp Pointer to allocated SIP request object * @param sip SIP Stack * @param stateful Stateful client transaction * @param met Null-terminated SIP Method string * @param uri Null-terminated Request URI string * @param route Next hop route URI (optional) * @param auth SIP authentication state * @param sendh Send handler * @param resph Response handler * @param arg Handler argument * @param fmt Formatted SIP headers * * @return 0 if success, otherwise errorcode */ int sip_requestf(struct sip_request **reqp, struct sip *sip, bool stateful, const char *met, const char *uri, const struct uri *route, struct sip_auth *auth, sip_send_h *sendh, sip_resp_h *resph, void *arg, const char *fmt, ...) { struct uri lroute; struct mbuf *mb; va_list ap; int err; if (!sip || !met || !uri || !fmt) return EINVAL; if (!route) { struct pl uripl; pl_set_str(&uripl, uri); err = uri_decode(&lroute, &uripl); if (err) return err; route = &lroute; } mb = mbuf_alloc(2048); if (!mb) return ENOMEM; err = mbuf_write_str(mb, "Max-Forwards: 70\r\n"); if (auth) err |= sip_auth_encode(mb, auth, met, uri); if (err) goto out; va_start(ap, fmt); err = mbuf_vprintf(mb, fmt, ap); va_end(ap); if (err) goto out; mb->pos = 0; err = sip_request(reqp, sip, stateful, met, -1, uri, -1, route, mb, sendh, resph, arg); if (err) goto out; out: mem_deref(mb); return err; }
/** * Decode URI field in-place * * @v uri URI * @v field URI field index */ static void uri_decode_inplace ( struct uri *uri, unsigned int field ) { const char *encoded = uri_field ( uri, field ); char *decoded = ( ( char * ) encoded ); size_t len; /* Do nothing if field is not present */ if ( ! encoded ) return; /* Decode field in place */ len = uri_decode ( encoded, decoded, strlen ( encoded ) ); /* Terminate decoded string */ decoded[len] = '\0'; }
/** * Update an existing SIP Dialog from a SIP Message * * @param dlg SIP Dialog to update * @param msg SIP Message * * @return 0 if success, otherwise errorcode */ int sip_dialog_update(struct sip_dialog *dlg, const struct sip_msg *msg) { const struct sip_hdr *contact; struct sip_addr addr; char *uri; int err; if (!dlg || !msg) return EINVAL; contact = sip_msg_hdr(msg, SIP_HDR_CONTACT); if (!contact) return EBADMSG; if (sip_addr_decode(&addr, &contact->val)) return EBADMSG; err = pl_strdup(&uri, &addr.auri); if (err) return err; if (dlg->route.scheme.p == dlg->uri) { struct uri tmp; struct pl pl; pl_set_str(&pl, uri); err = uri_decode(&tmp, &pl); if (err) goto out; dlg->route = tmp; } mem_deref(dlg->uri); dlg->uri = mem_ref(uri); out: mem_deref(uri); return err; }
/** * Parse URI * * @v uri_string URI as a string * @ret uri URI * * Splits a URI into its component parts. The return URI structure is * dynamically allocated and must eventually be freed by calling * uri_put(). */ struct uri * parse_uri ( const char *uri_string ) { struct uri *uri; char *raw; char *tmp; char *path = NULL; char *authority = NULL; int i; size_t raw_len; /* Allocate space for URI struct and a copy of the string */ raw_len = ( strlen ( uri_string ) + 1 /* NUL */ ); uri = zalloc ( sizeof ( *uri ) + raw_len ); if ( ! uri ) return NULL; raw = ( ( ( char * ) uri ) + sizeof ( *uri ) ); /* Copy in the raw string */ memcpy ( raw, uri_string, raw_len ); /* Start by chopping off the fragment, if it exists */ if ( ( tmp = strchr ( raw, '#' ) ) ) { *(tmp++) = '\0'; uri->fragment = tmp; } /* Identify absolute/relative URI. We ignore schemes that are * apparently only a single character long, since otherwise we * misinterpret a DOS-style path name ("C:\path\to\file") as a * URI with scheme="C",opaque="\path\to\file". */ if ( ( tmp = strchr ( raw, ':' ) ) && ( tmp > ( raw + 1 ) ) ) { /* Absolute URI: identify hierarchical/opaque */ uri->scheme = raw; *(tmp++) = '\0'; if ( *tmp == '/' ) { /* Absolute URI with hierarchical part */ path = tmp; } else { /* Absolute URI with opaque part */ uri->opaque = tmp; } } else { /* Relative URI */ path = raw; } /* If we don't have a path (i.e. we have an absolute URI with * an opaque portion, we're already finished processing */ if ( ! path ) goto done; /* Chop off the query, if it exists */ if ( ( tmp = strchr ( path, '?' ) ) ) { *(tmp++) = '\0'; uri->query = tmp; } /* Identify net/absolute/relative path */ if ( strncmp ( path, "//", 2 ) != 0 ) { /* Absolute/relative path */ uri->path = path; } else { /* Net path. If this is terminated by the first '/' * of an absolute path, then we have no space for a * terminator after the authority field, so shuffle * the authority down by one byte, overwriting one of * the two slashes. */ authority = ( path + 2 ); if ( ( tmp = strchr ( authority, '/' ) ) ) { /* Shuffle down */ uri->path = tmp; memmove ( ( authority - 1 ), authority, ( tmp - authority ) ); authority--; *(--tmp) = '\0'; } /* Split authority into user[:password] and host[:port] portions */ if ( ( tmp = strchr ( authority, '@' ) ) ) { /* Has user[:password] */ *(tmp++) = '\0'; uri->host = tmp; uri->user = authority; if ( ( tmp = strchr ( authority, ':' ) ) ) { /* Has password */ *(tmp++) = '\0'; uri->password = tmp; } } else { /* No user:password */ uri->host = authority; } /* Split host into host[:port] */ if ( ( tmp = strrchr ( uri->host, ':' ) ) ) { /* Make sure an IPv6 address isn't broken up. */ if ( ( tmp > strchr ( uri->host, ']' ) ) ) { *(tmp++) = '\0'; uri->port = tmp; } } /* Handle IPv6 case. */ if ( ( uri->host <= strchr ( uri->host, '[' ) ) && ( tmp = strchr ( uri->host, ']' ) ) ) { uri->host++; *(tmp) = 0; } } /* Decode fields that should be decoded */ for ( i = URI_FIRST_FIELD; i <= URI_LAST_FIELD; i++ ) { const char *field = uri_get_field ( uri, i ); if ( field && ( URI_ENCODED & ( 1 << i ) ) ) uri_decode ( field, ( char * ) field, strlen ( field ) + 1 /* NUL */ ); } done: DBG ( "URI \"%s\" split into", uri_string ); dump_uri ( uri ); DBG ( "\n" ); return uri; }
/** * Initialize a SIP Dialog from an incoming SIP Message * * @param dlg SIP Dialog to initialize * @param msg SIP Message * * @return 0 if success, otherwise errorcode */ int sip_dialog_create(struct sip_dialog *dlg, const struct sip_msg *msg) { char *uri = NULL, *rtag = NULL; const struct sip_hdr *contact; struct route_enc renc; struct sip_addr addr; struct pl pl; int err; if (!dlg || dlg->rtag || !dlg->cpos || !msg) return EINVAL; contact = sip_msg_hdr(msg, SIP_HDR_CONTACT); if (!contact) return EBADMSG; if (sip_addr_decode(&addr, &contact->val)) return EBADMSG; renc.mb = mbuf_alloc(512); if (!renc.mb) return ENOMEM; err = pl_strdup(&uri, &addr.auri); if (err) goto out; err = pl_strdup(&rtag, msg->req ? &msg->from.tag : &msg->to.tag); if (err) goto out; renc.end = 0; err |= sip_msg_hdr_apply(msg, msg->req, SIP_HDR_RECORD_ROUTE, record_route_handler, &renc) ? ENOMEM : 0; err |= mbuf_printf(renc.mb, "To: %r\r\n", msg->req ? &msg->from.val : &msg->to.val); dlg->mb->pos = dlg->cpos; err |= mbuf_write_mem(renc.mb, mbuf_buf(dlg->mb), mbuf_get_left(dlg->mb)); dlg->mb->pos = 0; if (err) goto out; renc.mb->pos = 0; if (renc.end) { pl.p = (const char *)mbuf_buf(renc.mb) + ROUTE_OFFSET; pl.l = renc.end - ROUTE_OFFSET; err = sip_addr_decode(&addr, &pl); if (err) goto out; dlg->route = addr.uri; } else { struct uri tmp; pl_set_str(&pl, uri); err = uri_decode(&tmp, &pl); if (err) goto out; dlg->route = tmp; } mem_deref(dlg->mb); mem_deref(dlg->uri); dlg->mb = mem_ref(renc.mb); dlg->rtag = mem_ref(rtag); dlg->uri = mem_ref(uri); dlg->rseq = msg->req ? msg->cseq.num : 0; dlg->cpos = 0; out: mem_deref(renc.mb); mem_deref(rtag); mem_deref(uri); return err; }
/** * Parse URI * * @v uri_string URI as a string * @ret uri URI * * Splits a URI into its component parts. The return URI structure is * dynamically allocated and must eventually be freed by calling * uri_put(). */ struct uri * parse_uri ( const char *uri_string ) { struct uri *uri; struct parameters *params; char *raw; char *tmp; char *path; char *authority; size_t raw_len; unsigned int field; /* Allocate space for URI struct and a copy of the string */ raw_len = ( strlen ( uri_string ) + 1 /* NUL */ ); uri = zalloc ( sizeof ( *uri ) + raw_len ); if ( ! uri ) return NULL; ref_init ( &uri->refcnt, uri_free ); raw = ( ( ( void * ) uri ) + sizeof ( *uri ) ); /* Copy in the raw string */ memcpy ( raw, uri_string, raw_len ); /* Identify the parameter list, if present */ if ( ( tmp = strstr ( raw, "##params" ) ) ) { *tmp = '\0'; tmp += 8 /* "##params" */; params = find_parameters ( *tmp ? ( tmp + 1 ) : NULL ); if ( params ) { uri->params = claim_parameters ( params ); } else { /* Ignore non-existent submission blocks */ } } /* Chop off the fragment, if it exists */ if ( ( tmp = strchr ( raw, '#' ) ) ) { *(tmp++) = '\0'; uri->fragment = tmp; } /* Identify absolute/relative URI */ if ( ( tmp = strchr ( raw, ':' ) ) ) { /* Absolute URI: identify hierarchical/opaque */ uri->scheme = raw; *(tmp++) = '\0'; if ( *tmp == '/' ) { /* Absolute URI with hierarchical part */ path = tmp; } else { /* Absolute URI with opaque part */ uri->opaque = tmp; path = NULL; } } else { /* Relative URI */ path = raw; } /* If we don't have a path (i.e. we have an absolute URI with * an opaque portion, we're already finished processing */ if ( ! path ) goto done; /* Chop off the query, if it exists */ if ( ( tmp = strchr ( path, '?' ) ) ) { *(tmp++) = '\0'; uri->query = tmp; } /* If we have no path remaining, then we're already finished * processing. */ if ( ! path[0] ) goto done; /* Identify net/absolute/relative path */ if ( strncmp ( path, "//", 2 ) == 0 ) { /* Net path. If this is terminated by the first '/' * of an absolute path, then we have no space for a * terminator after the authority field, so shuffle * the authority down by one byte, overwriting one of * the two slashes. */ authority = ( path + 2 ); if ( ( tmp = strchr ( authority, '/' ) ) ) { /* Shuffle down */ uri->path = tmp; memmove ( ( authority - 1 ), authority, ( tmp - authority ) ); authority--; *(--tmp) = '\0'; } } else { /* Absolute/relative path */ uri->path = path; authority = NULL; } /* If we don't have an authority (i.e. we have a non-net * path), we're already finished processing */ if ( ! authority ) goto done; /* Split authority into user[:password] and host[:port] portions */ if ( ( tmp = strchr ( authority, '@' ) ) ) { /* Has user[:password] */ *(tmp++) = '\0'; uri->host = tmp; uri->user = authority; if ( ( tmp = strchr ( authority, ':' ) ) ) { /* Has password */ *(tmp++) = '\0'; uri->password = tmp; } } else { /* No user:password */ uri->host = authority; } /* Split host into host[:port] */ if ( ( uri->host[ strlen ( uri->host ) - 1 ] != ']' ) && ( tmp = strrchr ( uri->host, ':' ) ) ) { *(tmp++) = '\0'; uri->port = tmp; } /* Decode fields in-place */ for ( field = 0 ; field < URI_FIELDS ; field++ ) { if ( uri_field ( uri, field ) ) uri_decode ( ( char * ) uri_field ( uri, field ) ); } done: DBGC ( uri, "URI parsed \"%s\" to", uri_string ); uri_dump ( uri ); DBGC ( uri, "\n" ); return uri; }
void Cconnection::read(const std::string& v) { #ifndef NDEBUG std::cout << v << std::endl; #endif if (srv_config().m_log_access) { static std::ofstream f("xbt_tracker_raw.log"); f << srv_time() << '\t' << inet_ntoa(m_a.sin_addr) << '\t' << ntohs(m_a.sin_port) << '\t' << v << std::endl; } Ctracker_input ti; size_t e = v.find('?'); if (e == std::string::npos) e = v.size(); else { size_t a = e + 1; size_t b = v.find(' ', a); if (b == std::string::npos) return; while (a < b) { size_t c = v.find('=', a); if (c++ == std::string::npos) break; size_t d = v.find_first_of(" &", c); if (d == std::string::npos) break; ti.set(v.substr(a, c - a - 1), uri_decode(v.substr(c, d - c))); a = d + 1; } } if (!ti.m_ipa || !is_private_ipa(m_a.sin_addr.s_addr)) ti.m_ipa = m_a.sin_addr.s_addr; str_ref torrent_pass; size_t a = 4; if (a < e && v[a] == '/') { a++; if (a + 32 < e && v[a + 32] == '/') { torrent_pass.assign(&v[a], 32); a += 33; } } std::string h = "HTTP/1.0 200 OK\r\n"; std::string s; bool gzip = true; switch (a < v.size() ? v[a] : 0) { case 'a': if (ti.valid()) { gzip = false; std::string error = srv_insert_peer(ti, false, find_user_by_torrent_pass(torrent_pass, ti.m_info_hash)); s = error.empty() ? srv_select_peers(ti) : (boost::format("d14:failure reason%d:%se") % error.size() % error).str(); } break; case 'd': if (srv_config().m_debug) { h += "Content-Type: text/html; charset=us-ascii\r\n"; s = srv_debug(ti); } break; case 's': if (v.size() >= 7 && v[6] == 't') { h += "Content-Type: text/html; charset=us-ascii\r\n"; s = srv_statistics(); } else if (srv_config().m_full_scrape || !ti.m_info_hash.empty()) { gzip = srv_config().m_gzip_scrape && ti.m_info_hash.empty(); s = srv_scrape(ti, find_user_by_torrent_pass(torrent_pass, ti.m_info_hash)); } break; } if (s.empty()) { if (!ti.m_info_hash.empty() || srv_config().m_redirect_url.empty()) h = "HTTP/1.0 404 Not Found\r\n"; else { h = "HTTP/1.0 302 Found\r\n" "Location: " + srv_config().m_redirect_url + (ti.m_info_hash.empty() ? "" : "?info_hash=" + uri_encode(ti.m_info_hash)) + "\r\n"; } } else if (gzip) { shared_data s2 = xcc_z::gzip(s); #ifndef NDEBUG static std::ofstream f("xbt_tracker_gzip.log"); f << srv_time() << '\t' << v[5] << '\t' << s.size() << '\t' << s2.size() << std::endl; #endif if (s2.size() + 24 < s.size()) { h += "Content-Encoding: gzip\r\n"; s = to_string(s2); } } h += "\r\n"; #ifdef WIN32 m_write_b = shared_data(h.size() + s.size()); memcpy(m_write_b.data(), h); memcpy(m_write_b.data() + h.size(), s); int r = m_s.send(m_write_b); #else std::array<iovec, 2> d; d[0].iov_base = const_cast<char*>(h.data()); d[0].iov_len = h.size(); d[1].iov_base = const_cast<char*>(s.data()); d[1].iov_len = s.size(); msghdr m; m.msg_name = NULL; m.msg_namelen = 0; m.msg_iov = const_cast<iovec*>(d.data()); m.msg_iovlen = d.size(); m.msg_control = NULL; m.msg_controllen = 0; m.msg_flags = 0; int r = sendmsg(m_s, &m, MSG_NOSIGNAL); #endif if (r == SOCKET_ERROR) { if (WSAGetLastError() != WSAECONNRESET) std::cerr << "send failed: " << Csocket::error2a(WSAGetLastError()) << std::endl; } else if (r != h.size() + s.size()) { #ifndef WIN32 if (r < h.size()) { m_write_b = shared_data(h.size() + s.size()); memcpy(m_write_b.data(), h); memcpy(m_write_b.data() + h.size(), s); } else { m_write_b = make_shared_data(s); r -= h.size(); } #endif m_r = m_write_b; m_r.advance_begin(r); } if (m_r.empty()) m_write_b.clear(); }
// ************************************************************************** // HTTPヘッダを受信して解析する。 // // 処理するのはGETのみ。GET以外のメソッドが来たらエラー // 今のところ、URIとuser_agent、Range、Hostを解析。 // URIは、URIデコードもやる。 // // return: 0 正常終了 // return: 0以外 エラー // ************************************************************************** static int http_header_receive(int accept_socket, HTTP_RECV_INFO *http_recv_info_p) { int result = 0; int recv_len; unsigned char line_buf[1024]; // 大きめに。 unsigned char work_buf[1024]; unsigned char work_buf2[1024]; unsigned char split1[1024]; unsigned char split2[1024]; int ret; int i; int j; // ================================ // 1行づつ HTTPヘッダを受信 // ================================ for (i=0;;i++) { // 1行受信 実行。 memset(line_buf, '\0', sizeof(line_buf)); recv_len = line_receive(accept_socket, line_buf, sizeof(line_buf)); // debug. 受信したヘッダ表示 debug_log_output("'%s'(%d byte)\n", line_buf, recv_len ); // 受信した内容をチェック。 if ( i != 0 && recv_len == 0 ) // 空行検知。ヘッダ受信終了。 { break; } else if ( recv_len < 0 ) // 受信失敗 { return ( -1 ); } // -------------------------- // GETメッセージチェック // -------------------------- if ( i == 0 ) // 1行目のみチェック { debug_log_output("URI Check start.'%s'\n", line_buf); // GET/POSTある? if (strncmp(line_buf, "GET ", 4) && strncmp(line_buf, "POST ", 5)) { debug_log_output("'GET' or 'POST' not found. error."); return ( -1 ); } strncpy(http_recv_info_p->request_method, line_buf, sizeof(http_recv_info_p->request_method)); cut_after_character(http_recv_info_p->request_method, ' '); // 最初のスペースまでを削除。 cut_before_character(line_buf, ' '); // 次にスペースが出てきたところの後ろまでを削除。 cut_after_character(line_buf, ' '); // =========================== // GETオプション部解析 // =========================== // REQUEST_URI用・Proxy用に値を保存 strncpy(http_recv_info_p->request_uri, line_buf, sizeof(http_recv_info_p->request_uri)); // '?'が存在するかチェック。 if ( strchr(line_buf, '?') != NULL ) { strncpy(work_buf, line_buf, sizeof(work_buf)); // '?'より前をカット cut_before_character(work_buf, '?' ); debug_log_output("work_buf = '%s'", work_buf ); while ( 1 ) { memset(split1, '\0', sizeof(split1)); memset(split2, '\0', sizeof(split2)); uri_decode(split1, sizeof(split1), work_buf, sizeof(work_buf) ); strcpy(work_buf, split1); // 最初に登場する'&'で分割 ret = sentence_split(work_buf, '&', split1, split2 ); if ( ret == 0 ) // 分割成功 { strncpy(work_buf, split2, sizeof(work_buf)); } else if (strlen(work_buf) > 0) // まだwork_bufに中身ある? { strncpy( split1, work_buf, sizeof(split1)); strncpy( work_buf, "", sizeof(work_buf)); } else // 処理終了 { break; } // ------------------------------------- // GETした内容 解析開始 // 超安直。いいのかこんな比較で。 // ------------------------------------- // URIデコード // uri_decode(work_buf2, sizeof(work_buf2), split1, sizeof(split1) ); strcpy(work_buf2, split1); // "page="あるか調査。 if (strncasecmp( work_buf2, "page=", strlen("page=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 http_recv_info_p->page = atoi(work_buf2); } continue; } // "menupage="あるか調査。 if (strncasecmp( work_buf2, "menupage=", strlen("menupage=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 http_recv_info_p->menupage = atoi(work_buf2); } continue; } // "title=" DVD title selection if (strncasecmp( work_buf2, "title=", strlen("title=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 http_recv_info_p->title = atoi(work_buf2); } continue; } if (strncasecmp( work_buf2, "width=", strlen("width=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 global_param.target_jpeg_width = atoi(work_buf2); } continue; } if (strncasecmp( work_buf2, "height=", strlen("height=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); if ( strlen(work_buf2) > 0 ) { // 構造体に値を保存。 global_param.target_jpeg_height = atoi(work_buf2); } continue; } // "action="あるか調査。 if (strncasecmp( work_buf2, "action=", strlen("action=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->action, work_buf2, sizeof(http_recv_info_p->action)); continue; } // "type=" allplay list type if (strncasecmp( work_buf2, "type=movie", strlen("type=movie") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_MOVIE; continue; } if (strncasecmp( work_buf2, "type=music", strlen("type=music") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_MUSIC; continue; } if (strncasecmp( work_buf2, "type=photo", strlen("type=photo") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_JPEG; continue; } if (strncasecmp( work_buf2, "type=soundtrack", strlen("type=soundtrack") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_MUSICLIST; continue; } if (strncasecmp( work_buf2, "type=slideshow", strlen("type=slideshow") ) == 0 ) { http_recv_info_p->default_file_type = TYPE_PLAYLIST; continue; } // "option="あるか調査 if (strncasecmp( work_buf2, "option=", strlen("option=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->option, work_buf2, sizeof(http_recv_info_p->option)); continue; } // "alias="あるか調査 if (strncasecmp( work_buf2, "alias=", strlen("alias=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->alias, work_buf2, sizeof(http_recv_info_p->alias)); if (strncasecmp(http_recv_info_p->alias, "movie", strlen("movie")) == 0) http_recv_info_p->default_file_type = TYPE_MOVIE; else if (strncasecmp(http_recv_info_p->alias, "music", strlen("music")) == 0) http_recv_info_p->default_file_type = TYPE_MUSIC; else if (strncasecmp(http_recv_info_p->alias, "photo", strlen("photo")) == 0) http_recv_info_p->default_file_type = TYPE_JPEG; else http_recv_info_p->default_file_type = TYPE_UNKNOWN; continue; } if (strncasecmp( work_buf2, "lsearch=", strlen("lsearch=") ) == 0 ) { cut_before_character(work_buf2, '='); strcpy(http_recv_info_p->lsearch, work_buf2); strcpy(http_recv_info_p->recv_uri, work_buf2); continue; } // "search= if (strncasecmp( work_buf2, "search", strlen("search") ) == 0 ) { if (strncasecmp(work_buf2, "search_movie", strlen("search_movie")) == 0) { http_recv_info_p->search_type = TYPE_MOVIE; strcpy(http_recv_info_p->search_str, "_movie"); http_recv_info_p->default_file_type = TYPE_MOVIE; // printf("search movie for "); } else if (strncasecmp(work_buf2, "search_music", strlen("search_music")) == 0) { http_recv_info_p->search_type = TYPE_MUSIC; strcpy(http_recv_info_p->search_str, "_music"); http_recv_info_p->default_file_type = TYPE_MUSIC; // printf("search music for "); } else if (strncasecmp(work_buf2, "search_photo", strlen("search_photo")) == 0) { http_recv_info_p->search_type = TYPE_JPEG; strcpy(http_recv_info_p->search_str, "_photo"); http_recv_info_p->default_file_type = TYPE_JPEG; // printf("search photo for "); } else if (strncasecmp(work_buf2, "search_all", strlen("search_all")) == 0) { http_recv_info_p->search_type = TYPE_UNKNOWN; strcpy(http_recv_info_p->search_str, "_all"); http_recv_info_p->default_file_type = TYPE_UNKNOWN; // printf("search all for "); } else continue; cut_before_character(work_buf2, '='); strncpy(http_recv_info_p->search, work_buf2, sizeof(http_recv_info_p->search)); if (http_recv_info_p->search[0] == '\0') // everything qualifies strcpy(http_recv_info_p->search, ".*"); // printf("%s\n", http_recv_info_p->search); continue; } // "sort="あるか調査 if (strncasecmp( work_buf2, "sort=", strlen("sort=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->sort, work_buf2, sizeof(http_recv_info_p->sort)); continue; } // "dvdopt="あるか調査 if (strncasecmp( work_buf2, "dvdopt=", strlen("dvdopt=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->dvdopt, work_buf2, sizeof(http_recv_info_p->dvdopt)); continue; } // "focus="あるか調査 if (strncasecmp( work_buf2, "focus=", strlen("focus=") ) == 0 ) { // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->focus, work_buf2, sizeof(http_recv_info_p->focus)); continue; } } } debug_log_output("http_recv_info_p->page = '%d'", http_recv_info_p->page); debug_log_output("http_recv_info_p->title = '%d'", http_recv_info_p->title); debug_log_output("http_recv_info_p->action = '%s'", http_recv_info_p->action); debug_log_output("http_recv_info_p->option = '%s'", http_recv_info_p->option); debug_log_output("http_recv_info_p->dvdopt = '%s'", http_recv_info_p->dvdopt); // URIデコード cut_after_character(line_buf, '?'); uri_decode(work_buf, sizeof(work_buf), line_buf, sizeof(line_buf) ); strncpy(line_buf, work_buf, sizeof(line_buf)); debug_log_output("URI(decoded):'%s'\n", line_buf); convert_language_code(line_buf, work_buf, sizeof(work_buf), CODE_AUTO, CODE_EUC); debug_log_output("URI(decoded,euc,FYI):'%s'\n", work_buf); // 構造体に保存 if (http_recv_info_p->lsearch[0] == '\0') strncpy(http_recv_info_p->recv_uri, line_buf, sizeof(http_recv_info_p->recv_uri)); continue; } // User-agent切り出し if ( strncasecmp(line_buf, HTTP_USER_AGENT, strlen(HTTP_USER_AGENT) ) == 0 ) { // ':'より前を切る cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // 構造体に保存 strncpy( http_recv_info_p->user_agent, line_buf, sizeof(http_recv_info_p->user_agent)); // Set the skin name based on user agent, if desired for(j=0; j<global_param.alternate_skin_count; j++) { debug_log_output("Checking for '%s'", global_param.alternate_skin_match[j]); if(strstr(line_buf, global_param.alternate_skin_match[j]) != NULL) { strcpy(global_param.skin_name, global_param.alternate_skin_name[j]); debug_log_output("User agent matches alternate skin '%s'", global_param.skin_name); break; } } continue; } // Rangeあるかチェック if ( strncasecmp(line_buf, HTTP_RANGE, strlen(HTTP_RANGE) ) == 0 ) { debug_log_output("%s Detect.\n", HTTP_RANGE); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // recv_range にRangeの中身保存 strncpy(http_recv_info_p->recv_range, line_buf, sizeof(http_recv_info_p->recv_range)); // '=' より前を切る cut_before_character(line_buf, '='); // '-'で前後に分割。 sentence_split(line_buf, '-', work_buf, work_buf2); debug_log_output("work_buf='%s'\n", work_buf); debug_log_output("work_buf2='%s'\n", work_buf2); // 値を文字列→数値変換 http_recv_info_p->range_start_pos = strtoull(work_buf, NULL, 10); if ( strlen(work_buf2) > 0 ) { http_recv_info_p->range_end_pos = strtoull(work_buf2, NULL, 10); } debug_log_output("range_start_pos=%d\n", http_recv_info_p->range_start_pos); debug_log_output("range_end_pos=%d\n", http_recv_info_p->range_end_pos); continue; } // Hostあるかチェック if ( strncasecmp(line_buf, HTTP_HOST, strlen(HTTP_HOST) ) == 0 ) { debug_log_output("%s Detect.\n", HTTP_HOST); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->recv_host, line_buf, sizeof(http_recv_info_p->recv_host)); if(NULL == strchr(http_recv_info_p->recv_host, ':')) { debug_log_output("CLIENT BUG: Host header field was missing port number - fixing"); snprintf(http_recv_info_p->recv_host + strlen(http_recv_info_p->recv_host), sizeof(http_recv_info_p->recv_host)-1, ":%d", global_param.server_port); debug_log_output("%s '%s'", HTTP_HOST, http_recv_info_p->recv_host); } continue; } if (strncasecmp(line_buf, HTTP_AUTHORIZATION, strlen(HTTP_AUTHORIZATION)) == 0) { debug_log_output("%s Detect.\n", HTTP_AUTHORIZATION); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); if (strncmp(line_buf, "Basic ", 6)) { debug_log_output("received '%s', is not supported.", line_buf); continue; } strncpy(http_recv_info_p->passwd, line_buf + 6, sizeof(http_recv_info_p->passwd)); continue; } // Content-Lengthあるかチェック if ( strncasecmp(line_buf, HTTP_CONTENT_LENGTH_STR, strlen(HTTP_CONTENT_LENGTH_STR) ) == 0 ) { debug_log_output("%s Detect.\n", HTTP_CONTENT_LENGTH_STR); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); /* recv_content_length は わざと long です. */ http_recv_info_p->recv_content_length = strtol(line_buf, NULL, 10); debug_log_output("Content-Length: %ld", http_recv_info_p->recv_content_length); continue; } } return result; }
void Cconnection::read(const std::string& v) { #ifndef NDEBUG std::cout << v << std::endl; #endif if (m_server->config().m_log_access) { static std::ofstream f("xbt_tracker_raw.log"); f << m_server->time() << '\t' << inet_ntoa(m_a.sin_addr) << '\t' << ntohs(m_a.sin_port) << '\t' << v << std::endl; } Ctracker_input ti; size_t e = v.find('?'); if (e == std::string::npos) e = v.size(); else { size_t a = e + 1; size_t b = v.find(' ', a); if (b == std::string::npos) return; while (a < b) { size_t c = v.find('=', a); if (c++ == std::string::npos) break; size_t d = v.find_first_of(" &", c); if (d == std::string::npos) break; ti.set(v.substr(a, c - a - 1), uri_decode(v.substr(c, d - c))); a = d + 1; } } if (!ti.m_ipa || !is_private_ipa(m_a.sin_addr.s_addr)) ti.m_ipa = m_a.sin_addr.s_addr; std::string torrent_pass0; size_t a = 4; if (a < e && v[a] == '/') { a++; if (a + 1 < e && v[a + 1] == '/') a += 2; if (a + 32 < e && v[a + 32] == '/') { torrent_pass0 = v.substr(a, 32); a += 33; if (a + 40 < e && v[a + 40] == '/') a += 41; } } std::string h = "HTTP/1.0 200 OK\r\n"; Cvirtual_binary s; bool gzip = true; switch (a < v.size() ? v[a] : 0) { case 'a': if (!ti.valid()) break; gzip = false; if (0) s = Cbvalue().d(bts_failure_reason, bts_banned_client).read(); else { std::string error = m_server->insert_peer(ti, false, m_server->find_user_by_torrent_pass(torrent_pass0, ti.m_info_hash)); s = error.empty() ? m_server->select_peers(ti) : Cbvalue().d(bts_failure_reason, error).read(); } break; case 'd': if (m_server->config().m_debug) { gzip = m_server->config().m_gzip_debug; h += "Content-Type: text/html; charset=us-ascii\r\n"; s = Cvirtual_binary(m_server->debug(ti)); } break; case 's': if (v.size() >= 7 && v[6] == 't') { gzip = m_server->config().m_gzip_debug; h += "Content-Type: text/html; charset=us-ascii\r\n"; s = Cvirtual_binary(m_server->statistics()); } else if (m_server->config().m_full_scrape || ti.m_compact || !ti.m_info_hash.empty()) { gzip = m_server->config().m_gzip_scrape && !ti.m_compact && ti.m_info_hash.empty(); s = m_server->scrape(ti); } break; } if (s.empty()) { if (!ti.m_peer_id.empty() || m_server->config().m_redirect_url.empty()) h = "HTTP/1.0 404 Not Found\r\n"; else { h = "HTTP/1.0 302 Found\r\n" "Location: " + m_server->config().m_redirect_url + (ti.m_info_hash.empty() ? "" : "?info_hash=" + uri_encode(ti.m_info_hash)) + "\r\n"; } } else if (gzip) { Cvirtual_binary s2 = xcc_z::gzip(s); #ifndef NDEBUG static std::ofstream f("xbt_tracker_gzip.log"); f << m_server->time() << '\t' << v[5] << '\t' << s.size() << '\t' << s2.size() << std::endl; #endif if (s2.size() + 24 < s.size()) { h += "Content-Encoding: gzip\r\n"; s = s2; } } h += "\r\n"; #ifdef WIN32 m_write_b.resize(h.size() + s.size()); memcpy(m_write_b.data_edit(), h.data(), h.size()); s.read(m_write_b.data_edit() + h.size()); int r = m_s.send(m_write_b); #else boost::array<iovec, 2> d; d[0].iov_base = const_cast<char*>(h.data()); d[0].iov_len = h.size(); d[1].iov_base = const_cast<unsigned char*>(s.data()); d[1].iov_len = s.size(); msghdr m; m.msg_name = NULL; m.msg_namelen = 0; m.msg_iov = const_cast<iovec*>(d.data()); m.msg_iovlen = d.size(); m.msg_control = NULL; m.msg_controllen = 0; m.msg_flags = 0; int r = sendmsg(m_s, &m, MSG_NOSIGNAL); #endif if (r == SOCKET_ERROR) { if (WSAGetLastError() != WSAECONNRESET) std::cerr << "send failed: " << Csocket::error2a(WSAGetLastError()) << std::endl; } else if (r != h.size() + s.size()) { #ifndef WIN32 if (r < h.size()) { m_write_b.resize(h.size() + s.size()); memcpy(m_write_b.data_edit(), h.data(), h.size()); s.read(m_write_b.data_edit() + h.size()); } else { m_write_b = s; r -= h.size(); } #endif m_r = m_write_b; m_r += r; } if (m_r.empty()) m_write_b.clear(); }
TEST(uri, test_uri_decode) { lwm2m_uri_t* uri; multi_option_t extraID = { .next = nullptr, .is_static = 1, .len = 3, .data = (uint8_t *) "555" }; multi_option_t rID = { .next = nullptr, .is_static = 1, .len = 1, .data = (uint8_t *) "0" }; multi_option_t iID = { .next = &rID, .is_static = 1, .len = 2, .data = (uint8_t *) "11" }; multi_option_t oID = { .next = &iID, .is_static = 1, .len = 4, .data = (uint8_t *) "9050" }; multi_option_t location = { .next = nullptr, .is_static = 1, .len = 4, .data = (uint8_t *) "5a3f" }; multi_option_t locationDecimal = { .next = nullptr, .is_static = 1, .len = 4, .data = (uint8_t *) "5312" }; multi_option_t reg = { .next = nullptr, .is_static = 1, .len = 2, .data = (uint8_t *) "rd" }; multi_option_t boot = { .next = nullptr, .is_static = 1, .len = 2, .data = (uint8_t *) "bs" }; memoryObserver.reset(); /* "/rd" */ uri = uri_decode(nullptr, ®); ASSERT_TRUE(uri); ASSERT_EQ(uri->flag, LWM2M_URI_FLAG_REGISTRATION); lwm2m_free(uri); /* "/rd/5a3f" */ reg.next = &location; uri = uri_decode(nullptr, ®); /* should not fail, error in uri_parse */ /* ASSERT_TRUE(uri); */ lwm2m_free(uri); /* "/rd/5312" */ reg.next = &locationDecimal; uri = uri_decode(nullptr, ®); ASSERT_TRUE(uri); ASSERT_EQ(uri->flag, LWM2M_URI_FLAG_REGISTRATION | LWM2M_URI_FLAG_OBJECT_ID); ASSERT_EQ(uri->objectId, 5312); lwm2m_free(uri); /* "/bs" */ uri = uri_decode(nullptr, &boot); ASSERT_TRUE(uri); ASSERT_EQ(uri->flag, LWM2M_URI_FLAG_BOOTSTRAP); lwm2m_free(uri); /* "/bs/5a3f" */ boot.next = &location; uri = uri_decode(nullptr, &boot); ASSERT_FALSE(uri); lwm2m_free(uri); /* "/9050/11/0" */ uri = uri_decode(nullptr, &oID); ASSERT_TRUE(uri); ASSERT_EQ(uri->flag, LWM2M_URI_FLAG_DM | LWM2M_URI_FLAG_OBJECT_ID | LWM2M_URI_FLAG_INSTANCE_ID | LWM2M_URI_FLAG_RESOURCE_ID); ASSERT_EQ(uri->objectId, 9050); ASSERT_EQ(uri->instanceId, 11); ASSERT_EQ(uri->resourceId, 0); lwm2m_free(uri); /* "/11/0" */ uri = uri_decode(nullptr, &iID); ASSERT_TRUE(uri); ASSERT_EQ(uri->flag, LWM2M_URI_FLAG_DM | LWM2M_URI_FLAG_OBJECT_ID | LWM2M_URI_FLAG_INSTANCE_ID); ASSERT_EQ(uri->objectId, 11); ASSERT_EQ(uri->instanceId, 0); lwm2m_free(uri); /* "/0" */ uri = uri_decode(nullptr, &rID); ASSERT_TRUE(uri); ASSERT_EQ(uri->flag, LWM2M_URI_FLAG_DM | LWM2M_URI_FLAG_OBJECT_ID); ASSERT_EQ(uri->objectId, 0); lwm2m_free(uri); /* "/9050/11/0/555" */ rID.next = &extraID; uri = uri_decode(nullptr, &oID); ASSERT_FALSE(uri); lwm2m_free(uri); /* "/0/5a3f" */ rID.next = &location; uri = uri_decode(nullptr, &rID); ASSERT_FALSE(uri); lwm2m_free(uri); MEMEVAL(FAIL()); } TEST(uri, test_string_to_uri) { int result; lwm2m_uri_t uri; memoryObserver.reset(); result = lwm2m_stringToUri("", 0, &uri); ASSERT_EQ(result, 0); result = lwm2m_stringToUri("no_uri", 6, &uri); ASSERT_EQ(result, 0); result = lwm2m_stringToUri("/1", 2, &uri); ASSERT_EQ(result, 2); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_OBJECT_ID), LWM2M_URI_FLAG_OBJECT_ID); ASSERT_EQ(uri.objectId, 1); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_INSTANCE_ID), 0); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_RESOURCE_ID), 0); result = lwm2m_stringToUri("/1/2", 4, &uri); ASSERT_EQ(result, 4); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_OBJECT_ID), LWM2M_URI_FLAG_OBJECT_ID); ASSERT_EQ(uri.objectId, 1); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_INSTANCE_ID), LWM2M_URI_FLAG_INSTANCE_ID); ASSERT_EQ(uri.instanceId, 2); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_RESOURCE_ID), 0); result = lwm2m_stringToUri("/1/2/3", 6, &uri); ASSERT_EQ(result, 6); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_OBJECT_ID), LWM2M_URI_FLAG_OBJECT_ID); ASSERT_EQ(uri.objectId, 1); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_INSTANCE_ID), LWM2M_URI_FLAG_INSTANCE_ID); ASSERT_EQ(uri.instanceId, 2); ASSERT_EQ((uri.flag & LWM2M_URI_FLAG_RESOURCE_ID), LWM2M_URI_FLAG_RESOURCE_ID); ASSERT_EQ(uri.resourceId, 3); MEMEVAL(FAIL()); }
/** * Decode a SIP message * * @param msgp Pointer to allocated SIP Message * @param mb Buffer containing SIP Message * * @return 0 if success, otherwise errorcode */ int sip_msg_decode(struct sip_msg **msgp, struct mbuf *mb) { struct pl x, y, z, e, name; const char *p, *v, *cv; struct sip_msg *msg; bool comsep, quote; enum sip_hdrid id = SIP_HDR_NONE; uint32_t ws, lf; size_t l; int err; if (!msgp || !mb) return EINVAL; p = (const char *)mbuf_buf(mb); l = mbuf_get_left(mb); if (re_regex(p, l, "[^ \t\r\n]+ [^ \t\r\n]+ [^\r\n]*[\r]*[\n]1", &x, &y, &z, NULL, &e) || x.p != (char *)mbuf_buf(mb)) return (l > STARTLINE_MAX) ? EBADMSG : ENODATA; msg = mem_zalloc(sizeof(*msg), destructor); if (!msg) return ENOMEM; err = hash_alloc(&msg->hdrht, HDR_HASH_SIZE); if (err) goto out; msg->tag = rand_u64(); msg->mb = mem_ref(mb); msg->req = (0 == pl_strcmp(&z, "SIP/2.0")); if (msg->req) { msg->met = x; msg->ruri = y; msg->ver = z; if (uri_decode(&msg->uri, &y)) { err = EBADMSG; goto out; } } else { msg->ver = x; msg->scode = pl_u32(&y); msg->reason = z; if (!msg->scode) { err = EBADMSG; goto out; } } l -= e.p + e.l - p; p = e.p + e.l; name.p = v = cv = NULL; name.l = ws = lf = 0; comsep = false; quote = false; for (; l > 0; p++, l--) { switch (*p) { case ' ': case '\t': lf = 0; /* folding */ ++ws; break; case '\r': ++ws; break; case '\n': ++ws; if (!lf++) break; ++p; --l; /* eoh */ /*@fallthrough@*/ default: if (lf || (*p == ',' && comsep && !quote)) { if (!name.l) { err = EBADMSG; goto out; } err = hdr_add(msg, &name, id, cv ? cv : p, cv ? p - cv - ws : 0, true, cv == v && lf); if (err) goto out; if (!lf) { /* comma separated */ cv = NULL; break; } if (cv != v) { err = hdr_add(msg, &name, id, v ? v : p, v ? p - v - ws : 0, false, true); if (err) goto out; } if (lf > 1) { /* eoh */ err = 0; goto out; } comsep = false; name.p = NULL; cv = v = NULL; lf = 0; } if (!name.p) { name.p = p; name.l = 0; ws = 0; } if (!name.l) { if (*p != ':') { ws = 0; break; } name.l = MAX((int)(p - name.p - ws), 0); if (!name.l) { err = EBADMSG; goto out; } id = hdr_hash(&name); comsep = hdr_comma_separated(id); break; } if (!cv) { quote = false; cv = p; } if (!v) { v = p; } if (*p == '"') quote = !quote; ws = 0; break; } } err = ENODATA; out: if (err) mem_deref(msg); else { *msgp = msg; mb->pos = mb->end - l; } return err; }
// ************************************************************************** // HTTPヘッダを受信して解析する。 // // 処理するのはGETのみ。GET以外のメソッドが来たらエラー // 今のところ、URIとuser_agent、Range、Hostを解析。 // URIは、URIデコードもやる。 // // return: 0 正常終了 // return: 0以外 エラー // ************************************************************************** static int http_header_receive(int accept_socket, HTTP_RECV_INFO *http_recv_info_p) { int result = 0; int recv_len; char line_buf[1024]; // 大きめに。 char work_buf[1024]; char work_buf2[1024]; char split1[1024]; char split2[1024]; int ret; int i; // ================================ // 1行づつ HTTPヘッダを受信 // ================================ for (i=0;;i++){ // 1行受信 実行。 recv_len = line_receive(accept_socket, line_buf, sizeof(line_buf)); // 受信した内容をチェック。 if ( recv_len == 0 ){ // 空行検知。ヘッダ受信終了。 break; }else if ( recv_len < 0 ){ // 受信失敗 return ( -1 ); } // debug. 受信したヘッダ表示 debug_log_output("'%s'(%d byte)\n", line_buf, recv_len ); // -------------------------- // GETメッセージチェック // -------------------------- if ( i == 0 ){ // 1行目のみチェック debug_log_output("%d:URI Check start.'%s'\n", accept_socket,line_buf); // GETある? if ( strstr(line_buf, "GET") != NULL ){ http_recv_info_p->isGet = 1; }else if ( strstr(line_buf, "HEAD") != NULL ){ http_recv_info_p->isGet = 2; }else if ( strstr(line_buf, "POST") != NULL ){ http_recv_info_p->isGet = 3; }else{ debug_log_output("'GET' not found. error.%d",accept_socket); return ( -1 ); } // 最初のスペースまでを削除。 cut_before_character(line_buf, ' '); // 次にスペースが出てきたところの後ろまでを削除。 cut_after_character(line_buf, ' '); // =========================== // GETオプション部解析 // =========================== // REQUEST_URI用・Proxy用に値を保存 strncpy(http_recv_info_p->request_uri, line_buf, sizeof(http_recv_info_p->request_uri)); // '?'が存在するかチェック。 if ( strchr(line_buf, '?') != NULL ){ strncpy(work_buf, line_buf, sizeof(work_buf)); // '?'より前をカット cut_before_character(work_buf, '?' ); while ( 1 ){ memset(split1, 0, sizeof(split1)); memset(split2, 0, sizeof(split2)); // 最初に登場する'&'で分割 ret = sentence_split(work_buf, '&', split1, split2 ); if ( ret == 0 ){ // 分割成功 strncpy(work_buf, split2, sizeof(work_buf)); }else if (strlen(work_buf) > 0){ // まだwork_bufに中身ある? strncpy( split1, work_buf, sizeof(split1)); strncpy( work_buf, "", sizeof(work_buf)); }else{ // 処理終了 break; } // ------------------------------------- // GETした内容 解析開始 // 超安直。いいのかこんな比較で。 // ------------------------------------- // URIデコード uri_decode(work_buf2, sizeof(work_buf2), split1, sizeof(split1) ); // "action="あるか調査。 if (strncasecmp( work_buf2, "action=", strlen("action=") ) == 0 ){ // = より前を削除 cut_before_character(work_buf2, '='); // 構造体に値を保存。 strncpy(http_recv_info_p->action, work_buf2, sizeof(http_recv_info_p->action)); continue; } } } debug_log_output("http_recv_info_p->action = '%s'", http_recv_info_p->action); // URIデコード cut_after_character(line_buf, '?'); uri_decode(work_buf, sizeof(work_buf), line_buf, sizeof(line_buf) ); strncpy(line_buf, work_buf, sizeof(line_buf)); debug_log_output("URI(decoded):'%s'\n", line_buf); convert_language_code(line_buf, work_buf, sizeof(work_buf), CODE_AUTO, CODE_EUC); debug_log_output("URI(decoded,euc,FYI):'%s'\n", work_buf); // 構造体に保存 strncpy(http_recv_info_p->recv_uri, line_buf, sizeof(http_recv_info_p->recv_uri)); //httpから始まってる場合には、http://以降の最初の'/'の前でカット if( strncmp(http_recv_info_p->recv_uri,"http://",7)==0){ char* ptr = strstr(http_recv_info_p->recv_uri+7,"/"); if( ptr ){ strcpy(http_recv_info_p->recv_uri,ptr); } } continue; } // User-agent切り出し if ( strncasecmp(line_buf, HTTP_USER_AGENT, strlen(HTTP_USER_AGENT) ) == 0 ){ debug_log_output("User-agent: Detect.\n"); // ':'より前を切る cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // 構造体に保存 strncpy( http_recv_info_p->user_agent, line_buf, sizeof(http_recv_info_p->user_agent)); continue; } // Rangeあるかチェック if ( strncasecmp(line_buf, HTTP_RANGE, strlen(HTTP_RANGE) ) == 0 ){ debug_log_output("%s Detect.\n", HTTP_RANGE); // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); // recv_range にRangeの中身保存 strncpy(http_recv_info_p->recv_range, line_buf, sizeof(http_recv_info_p->recv_range)); // '=' より前を切る cut_before_character(line_buf, '='); // '-'で前後に分割。 sentence_split(line_buf, '-', work_buf, work_buf2); debug_log_output("wrok_buf='%s'\n", work_buf); debug_log_output("wrok_buf2='%s'\n", work_buf2); // 値を文字列→数値変換 http_recv_info_p->range_start_pos = strtoull(work_buf, NULL, 10); if ( strlen(work_buf2) > 0 ){ http_recv_info_p->range_end_pos = strtoull(work_buf2, NULL, 10); } debug_log_output("range_start_pos=%d\n", http_recv_info_p->range_start_pos); debug_log_output("range_end_pos=%d\n", http_recv_info_p->range_end_pos); continue; } // Hostあるかチェック if ( strncasecmp(line_buf, HTTP_HOST, strlen(HTTP_HOST) ) == 0 ){ // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->recv_host, line_buf, sizeof(http_recv_info_p->recv_host)); debug_log_output("%s Detect. %s '%s'", HTTP_HOST, HTTP_HOST, http_recv_info_p->recv_host); continue; } // Content-Lengthあるかチェック if ( strncasecmp(line_buf, HTTP_CONTENT_LENGTH1, strlen(HTTP_CONTENT_LENGTH1) ) == 0 ){ // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->content_length, line_buf, sizeof(http_recv_info_p->content_length)); debug_log_output("%s Detect. %s '%s'", HTTP_CONTENT_LENGTH1, HTTP_CONTENT_LENGTH1, http_recv_info_p->content_length); continue; } // Content-TYPEあるかチェック if ( strncasecmp(line_buf, HTTP_CONTENT_TYPE1, strlen(HTTP_CONTENT_TYPE1) ) == 0 ){ // ':' より前を切る。 cut_before_character(line_buf, ':'); cut_first_character(line_buf, ' '); strncpy(http_recv_info_p->content_type, line_buf, sizeof(http_recv_info_p->content_type)); debug_log_output("%s Detect. %s '%s'", HTTP_CONTENT_TYPE1, HTTP_CONTENT_TYPE1, http_recv_info_p->content_type); continue; } } return result; }
static coap_status_t handle_request(lwm2m_context_t * contextP, void * fromSessionH, coap_packet_t * message, coap_packet_t * response) { lwm2m_uri_t * uriP; coap_status_t result = COAP_IGNORE; #ifdef LWM2M_CLIENT_MODE uriP = uri_decode(contextP->altPath, message->uri_path); #else uriP = uri_decode(NULL, message->uri_path); #endif if (uriP == NULL) return COAP_400_BAD_REQUEST; switch(uriP->flag & LWM2M_URI_MASK_TYPE) { #ifdef LWM2M_CLIENT_MODE case LWM2M_URI_FLAG_DM: { lwm2m_server_t * serverP; serverP = utils_findServer(contextP, fromSessionH); if (serverP != NULL) { result = dm_handleRequest(contextP, uriP, serverP, message, response); } #ifdef LWM2M_BOOTSTRAP else { serverP = utils_findBootstrapServer(contextP, fromSessionH); if (serverP != NULL) { result = bootstrap_handleCommand(contextP, uriP, serverP, message, response); } } #endif } break; #ifdef LWM2M_BOOTSTRAP case LWM2M_URI_FLAG_DELETE_ALL: if (COAP_DELETE != message->code) { result = COAP_400_BAD_REQUEST; } else { result = bootstrap_handleDeleteAll(contextP, fromSessionH); } break; case LWM2M_URI_FLAG_BOOTSTRAP: if (message->code == COAP_POST) { result = bootstrap_handleFinish(contextP, fromSessionH); } break; #endif #endif #ifdef LWM2M_SERVER_MODE case LWM2M_URI_FLAG_REGISTRATION: result = registration_handleRequest(contextP, uriP, fromSessionH, message, response); break; #endif #ifdef LWM2M_BOOTSTRAP_SERVER_MODE case LWM2M_URI_FLAG_BOOTSTRAP: result = bootstrap_handleRequest(contextP, uriP, fromSessionH, message, response); break; #endif default: result = COAP_IGNORE; break; } coap_set_status_code(response, result); if (COAP_IGNORE < result && result < COAP_400_BAD_REQUEST) { result = NO_ERROR; } lwm2m_free(uriP); return result; }
int location_update(struct list *locl, const struct sip_msg *msg, const struct sip_addr *contact, uint32_t expires) { struct location *loc, *loc_new = NULL; struct loctmp *tmp; struct pl pl; int err; if (!locl || !msg || !contact) return EINVAL; loc = list_ledata(list_apply(locl, true, cmp_handler, (void *)&contact->uri)); if (!loc) { if (expires == 0) return 0; loc = loc_new = mem_zalloc(sizeof(*loc), destructor_location); if (!loc) return ENOMEM; list_append(locl, &loc->le, loc); } else { if (!pl_strcmp(&msg->callid, loc->callid) && msg->cseq.num <= loc->cseq) return EPROTO; if (expires == 0) { loc->rm = true; return 0; } } tmp = mem_zalloc(sizeof(*tmp), destructor_loctmp); if (!tmp) { err = ENOMEM; goto out; } err = pl_strdup(&tmp->uri, &contact->auri); if (err) goto out; pl_set_str(&pl, tmp->uri); if (uri_decode(&tmp->duri, &pl)) { err = EBADMSG; goto out; } err = pl_strdup(&tmp->callid, &msg->callid); if (err) goto out; if (!msg_param_decode(&contact->params, "q", &pl)) tmp->q = pl_float(&pl); else tmp->q = 1; tmp->cseq = msg->cseq.num; tmp->expires = expires; tmp->src = msg->src; out: if (err) { mem_deref(loc_new); mem_deref(tmp); } else { mem_deref(loc->tmp); loc->tmp = tmp; } return err; }
/** * Allocate a SIP Dialog * * @param dlgp Pointer to allocated SIP Dialog * @param uri Target URI * @param to_uri To URI * @param from_name From displayname (optional) * @param from_uri From URI * @param routev Route vector * @param routec Route count * * @return 0 if success, otherwise errorcode */ int sip_dialog_alloc(struct sip_dialog **dlgp, const char *uri, const char *to_uri, const char *from_name, const char *from_uri, const char *routev[], uint32_t routec) { const uint64_t ltag = rand_u64(); struct sip_dialog *dlg; struct sip_addr addr; size_t rend = 0; struct pl pl; uint32_t i; int err; if (!dlgp || !uri || !to_uri || !from_uri) return EINVAL; dlg = mem_zalloc(sizeof(*dlg), destructor); if (!dlg) return ENOMEM; dlg->lseq = rand_u16(); err = str_dup(&dlg->uri, uri); if (err) goto out; err = x64_strdup(&dlg->callid, rand_u64()); if (err) goto out; err = x64_strdup(&dlg->ltag, ltag); if (err) goto out; dlg->mb = mbuf_alloc(512); if (!dlg->mb) { err = ENOMEM; goto out; } for (i=0; i<routec; i++) { err |= mbuf_printf(dlg->mb, "Route: <%s;lr>\r\n", routev[i]); if (i == 0) rend = dlg->mb->pos - 2; } err |= mbuf_printf(dlg->mb, "To: <%s>\r\n", to_uri); dlg->cpos = dlg->mb->pos; err |= mbuf_printf(dlg->mb, "From: %s%s%s<%s>;tag=%016llx\r\n", from_name ? "\"" : "", from_name, from_name ? "\" " : "", from_uri, ltag); if (err) goto out; dlg->mb->pos = 0; if (rend) { pl.p = (const char *)mbuf_buf(dlg->mb) + ROUTE_OFFSET; pl.l = rend - ROUTE_OFFSET; err = sip_addr_decode(&addr, &pl); dlg->route = addr.uri; } else { pl_set_str(&pl, dlg->uri); err = uri_decode(&dlg->route, &pl); } out: if (err) mem_deref(dlg); else *dlgp = dlg; return err; }
int stun_uri_decode(struct stun_uri *stun_uri, const char *str) { struct uri uri; struct pl pl_uri; uint16_t port; struct pl transp; int err; if (!stun_uri || !str) return EINVAL; pl_set_str(&pl_uri, str); err = uri_decode(&uri, &pl_uri); if (err) { warning("cannot decode URI (%r)\n", &pl_uri); return err; } if (0 == pl_strcasecmp(&uri.scheme, "stun") || 0 == pl_strcasecmp(&uri.scheme, "stuns")) { stun_uri->scheme = STUN_SCHEME_STUN; } else if (0 == pl_strcasecmp(&uri.scheme, "turn") || 0 == pl_strcasecmp(&uri.scheme, "turns")) { stun_uri->scheme = STUN_SCHEME_TURN; } else { warning("unsupported stun scheme (%r)\n", &uri.scheme); return ENOTSUP; } stun_uri->secure = 's' == tolower(uri.scheme.p[uri.scheme.l-1]); if (uri.port) port = uri.port; else if (stun_uri->secure) port = 5349; else port = 3478; err = sa_set(&stun_uri->addr, &uri.host, port); if (err) { warning("invalid stun address (%r)\n", &uri.host); return err; } if (0 == re_regex(str, strlen(str), "?transport=[a-z]+", &transp)) { if (0 == pl_strcasecmp(&transp, "udp")) stun_uri->proto = IPPROTO_UDP; else if (0 == pl_strcasecmp(&transp, "tcp")) stun_uri->proto = IPPROTO_TCP; else { warning("unsupported stun transport (%r)\n", &transp); return ENOTSUP; } } else { stun_uri->proto = IPPROTO_UDP; } return 0; }
static uint8_t handle_request(lwm2m_context_t * contextP, void * fromSessionH, coap_packet_t * message, coap_packet_t * response) { lwm2m_uri_t uri; lwm2m_request_type_t requestType; uint8_t result = COAP_IGNORE; LOG("Entering"); #ifdef LWM2M_CLIENT_MODE requestType = uri_decode(contextP->altPath, message->uri_path, &uri); #else requestType = uri_decode(NULL, message->uri_path, &uri); #endif switch(requestType) { case LWM2M_REQUEST_TYPE_UNKNOWN: return COAP_400_BAD_REQUEST; #ifdef LWM2M_CLIENT_MODE case LWM2M_REQUEST_TYPE_DM: { lwm2m_server_t * serverP; serverP = utils_findServer(contextP, fromSessionH); if (serverP != NULL) { result = dm_handleRequest(contextP, &uri, serverP, message, response); } #ifdef LWM2M_BOOTSTRAP else { serverP = utils_findBootstrapServer(contextP, fromSessionH); if (serverP != NULL) { result = bootstrap_handleCommand(contextP, &uri, serverP, message, response); } } #endif } break; #ifdef LWM2M_BOOTSTRAP case LWM2M_REQUEST_TYPE_DELETE_ALL: if (COAP_DELETE != message->code) { result = COAP_400_BAD_REQUEST; } else { result = bootstrap_handleDeleteAll(contextP, fromSessionH); } break; case LWM2M_REQUEST_TYPE_BOOTSTRAP: if (message->code == COAP_POST) { result = bootstrap_handleFinish(contextP, fromSessionH); } break; #endif #endif #ifdef LWM2M_SERVER_MODE case LWM2M_REQUEST_TYPE_REGISTRATION: result = registration_handleRequest(contextP, &uri, fromSessionH, message, response); break; #endif #ifdef LWM2M_BOOTSTRAP_SERVER_MODE case LWM2M_REQUEST_TYPE_BOOTSTRAP: result = bootstrap_handleRequest(contextP, &uri, fromSessionH, message, response); break; #endif default: result = COAP_IGNORE; break; } coap_set_status_code(response, result); if (COAP_IGNORE < result && result < COAP_400_BAD_REQUEST) { result = NO_ERROR; } return result; }
/** * e_uri_new: * @uri_string: The uri to represent as an #EUri. * * Creates an #EUri representation of the uri given in @uri_string. * * Returns: The newly-allocated #EUri structure. **/ EUri * e_uri_new (const gchar *uri_string) { EUri *uri; const gchar *end, *hash, *colon, *semi, *at, *slash, *question; const gchar *p; if (!uri_string) return NULL; uri = g_new0 (EUri, 1); /* find fragment */ end = hash = strchr (uri_string, '#'); if (hash && hash[1]) { uri->fragment = g_strdup (hash + 1); uri_decode (uri->fragment); } else end = uri_string + strlen (uri_string); /* find protocol: initial [a-z+.-]* substring until ":" */ p = uri_string; while (p < end && (isalnum ((guchar) *p) || *p == '.' || *p == '+' || *p == '-')) p++; if (p > uri_string && *p == ':') { uri->protocol = g_ascii_strdown (uri_string, p - uri_string); uri_string = p + 1; } else uri->protocol = g_strdup ("file"); if (!*uri_string) return uri; /* check for authority */ if (strncmp (uri_string, "//", 2) == 0) { uri_string += 2; slash = uri_string + strcspn (uri_string, "/#"); at = strchr (uri_string, '@'); if (at && at < slash) { const gchar *at2; /* this is for cases where username contains '@' at it, like: * http://[email protected]@server.addr.com/path * We skip all at-s before the slash here. */ while (at2 = strchr (at + 1, '@'), at2 && at2 < slash) { at = at2; } } if (at && at < slash) { colon = strchr (uri_string, ':'); if (colon && colon < at) { uri->passwd = g_strndup (colon + 1, at - colon - 1); uri_decode (uri->passwd); } else { uri->passwd = NULL; colon = at; } semi = strchr (uri_string, ';'); if (semi && semi < colon && !g_ascii_strncasecmp (semi, ";auth=", 6)) { uri->authmech = g_strndup (semi + 6, colon - semi - 6); uri_decode (uri->authmech); } else { uri->authmech = NULL; semi = colon; } uri->user = g_strndup (uri_string, semi - uri_string); uri_decode (uri->user); uri_string = at + 1; } else uri->user = uri->passwd = uri->authmech = NULL; /* find host and port */ colon = strchr (uri_string, ':'); if (colon && colon < slash) { uri->host = g_strndup (uri_string, colon - uri_string); uri->port = strtoul (colon + 1, NULL, 10); } else { uri->host = g_strndup (uri_string, slash - uri_string); uri_decode (uri->host); uri->port = 0; } uri_string = slash; } /* find query */ question = memchr (uri_string, '?', end - uri_string); if (question) { if (question[1]) { uri->query = g_strndup (question + 1, end - (question + 1)); uri_decode (uri->query); } end = question; } /* find parameters */ semi = memchr (uri_string, ';', end - uri_string); if (semi) { if (semi[1]) { const gchar *cur, *ptr, *eq; gchar *name, *value; for (cur = semi + 1; cur < end; cur = ptr + 1) { ptr = memchr (cur, ';', end - cur); if (!ptr) ptr = end; eq = memchr (cur, '=', ptr - cur); if (eq) { name = g_strndup (cur, eq - cur); value = g_strndup (eq + 1, ptr - (eq + 1)); uri_decode (value); } else { name = g_strndup (cur, ptr - cur); value = g_strdup (""); } uri_decode (name); g_datalist_set_data_full ( &uri->params, name, value, g_free); g_free (name); } } end = semi; } if (end != uri_string) { uri->path = g_strndup (uri_string, end - uri_string); uri_decode (uri->path); } return uri; }
/** * Fork a SIP Dialog from an incoming SIP Message * * @param dlgp Pointer to allocated SIP Dialog * @param odlg Original SIP Dialog * @param msg SIP Message * * @return 0 if success, otherwise errorcode */ int sip_dialog_fork(struct sip_dialog **dlgp, struct sip_dialog *odlg, const struct sip_msg *msg) { const struct sip_hdr *contact; struct sip_dialog *dlg; struct route_enc renc; struct sip_addr addr; struct pl pl; int err; if (!dlgp || !odlg || !odlg->cpos || !msg) return EINVAL; contact = sip_msg_hdr(msg, SIP_HDR_CONTACT); if (!contact || !msg->callid.p) return EBADMSG; if (sip_addr_decode(&addr, &contact->val)) return EBADMSG; dlg = mem_zalloc(sizeof(*dlg), destructor); if (!dlg) return ENOMEM; dlg->callid = mem_ref(odlg->callid); dlg->ltag = mem_ref(odlg->ltag); dlg->lseq = odlg->lseq; dlg->rseq = msg->req ? msg->cseq.num : 0; err = pl_strdup(&dlg->uri, &addr.auri); if (err) goto out; err = pl_strdup(&dlg->rtag, msg->req ? &msg->from.tag : &msg->to.tag); if (err) goto out; dlg->mb = mbuf_alloc(512); if (!dlg->mb) { err = ENOMEM; goto out; } renc.mb = dlg->mb; renc.end = 0; err |= sip_msg_hdr_apply(msg, msg->req, SIP_HDR_RECORD_ROUTE, record_route_handler, &renc) ? ENOMEM : 0; err |= mbuf_printf(dlg->mb, "To: %r\r\n", msg->req ? &msg->from.val : &msg->to.val); odlg->mb->pos = odlg->cpos; err |= mbuf_write_mem(dlg->mb, mbuf_buf(odlg->mb), mbuf_get_left(odlg->mb)); odlg->mb->pos = 0; if (err) goto out; dlg->mb->pos = 0; if (renc.end) { pl.p = (const char *)mbuf_buf(dlg->mb) + ROUTE_OFFSET; pl.l = renc.end - ROUTE_OFFSET; err = sip_addr_decode(&addr, &pl); dlg->route = addr.uri; } else { pl_set_str(&pl, dlg->uri); err = uri_decode(&dlg->route, &pl); } out: if (err) mem_deref(dlg); else *dlgp = dlg; return err; }