📄 wap_push_ppg.c
字号:
enum { TYPE_HTTP = 0, TYPE_HTTPS = 1};void wap_push_ppg_init(wap_dispatch_func_t *ota_dispatch, wap_dispatch_func_t *appl_dispatch, Cfg *cfg){ user_configuration = read_ppg_config(cfg); if (user_configuration != USER_CONFIGURATION_NOT_ADDED) { ppg_queue = list_create(); list_add_producer(ppg_queue); pap_queue = list_create(); list_add_producer(pap_queue); push_id_counter = counter_create(); ppg_machines = list_create(); ppg_unit_pushes = list_create(); dispatch_to_ota = ota_dispatch; dispatch_to_appl = appl_dispatch; http_open_port(ppg_port, TYPE_HTTP);#ifdef HAVE_LIBSSL if (ppg_ssl_port != NO_HTTPS_PORT) http_open_port(ppg_ssl_port, TYPE_HTTPS);#endif http_clients = dict_create(number_of_pushes, NULL); urls = dict_create(number_of_pushes, NULL); gw_assert(run_status == limbo); run_status = running; gwthread_create(ota_read_thread, NULL); gwthread_create(http_read_thread, NULL);#ifdef HAVE_LIBSSL if (ppg_ssl_port != NO_HTTPS_PORT) gwthread_create(https_read_thread, NULL);#endif gwthread_create(pap_request_thread, NULL); }}void wap_push_ppg_shutdown(void){ if (user_configuration != USER_CONFIGURATION_NOT_ADDED) { gw_assert(run_status == running); run_status = terminating; list_remove_producer(ppg_queue); list_remove_producer(pap_queue); octstr_destroy(ppg_url); http_close_all_ports(); dict_destroy(http_clients); dict_destroy(urls); wap_push_ppg_pushuser_list_destroy(); octstr_destroy(ppg_deny_ip); octstr_destroy(ppg_allow_ip); octstr_destroy(global_sender); octstr_destroy(service_name); octstr_destroy(ppg_default_smsc); gwthread_join_every(http_read_thread);#ifdef HAVE_LIBSSL if (ppg_ssl_port != NO_HTTPS_PORT) gwthread_join_every(https_read_thread);#endif gwthread_join_every(ota_read_thread); gwthread_join_every(pap_request_thread); list_destroy(ppg_queue, wap_event_destroy_item); list_destroy(pap_queue, pap_event_destroy_item); counter_destroy(push_id_counter); debug("wap.push.ppg", 0, "PPG: %ld push session machines left.", list_len(ppg_machines)); list_destroy(ppg_machines, session_machine_destroy); debug("wap_push_ppg", 0, "PPG: %ld unit pushes left", list_len(ppg_unit_pushes)); list_destroy(ppg_unit_pushes, push_machine_destroy); }}void wap_push_ppg_dispatch_event(WAPEvent *e){ gw_assert(run_status == running); list_produce(ppg_queue, e);}/* * We cannot know port the client is using when it establish the connection. * However, we must link session creation with a pending push request. Only * data available is the client address, so we check it here. * Return non-NULL (pointer to the session machine found), if we have one. */PPGSessionMachine *wap_push_ppg_have_push_session_for(WAPAddrTuple *tuple){ PPGSessionMachine *sm; gw_assert(tuple); sm = list_search(ppg_machines, tuple->remote->address, session_has_addr); return sm;}/* * Now initiators are identified by their session id. Return non-NULL (pointer * to the session machine found), if we have one. This function are used after * wsp has indicated session establishment, giving us a session id. */PPGSessionMachine *wap_push_ppg_have_push_session_for_sid(long sid){ PPGSessionMachine *sm; gw_assert(sid >= 0); sm = list_search(ppg_machines, &sid, session_has_sid); return sm;}/***************************************************************************** * * INTERNAL FUNCTIONS * * Read general ppg configuration and configuration specific for users (to the * list 'users'). * Return 1 when an user ppg group is present, 0 otherwise (and panic * if we have not trusted ppg and no user groups). */static int read_ppg_config(Cfg *cfg){ CfgGroup *grp; List *list; if (cfg == NULL) return USER_CONFIGURATION_NOT_ADDED; grp = cfg_get_single_group(cfg, octstr_imm("ppg")); if ((ppg_url = cfg_get(grp, octstr_imm("ppg-url"))) == NULL) ppg_url = octstr_imm("/wappush"); cfg_get_integer(&ppg_port, grp, octstr_imm("ppg-port")); cfg_get_integer(&number_of_pushes, grp, octstr_imm("concurrent-pushes")); cfg_get_bool(&trusted_pi, grp, octstr_imm("trusted-pi")); cfg_get_integer(&number_of_users, grp, octstr_imm("users")); ppg_deny_ip = cfg_get(grp, octstr_imm("ppg-deny-ip")); ppg_allow_ip = cfg_get(grp, octstr_imm("ppg-allow-ip")); if ((global_sender = cfg_get(grp, octstr_imm("global-sender"))) == NULL) global_sender = octstr_format("%s", "1234"); ppg_default_smsc = cfg_get(grp, octstr_imm("default-smsc")); ppg_dlr_url = cfg_get(grp, octstr_imm("default-dlr-url")); ppg_smsbox_id = cfg_get(grp, octstr_imm("ppg-smsbox-id")); if ((service_name = cfg_get(grp, octstr_imm("service-name"))) == NULL) service_name = octstr_format("%s", "ppg"); #ifdef HAVE_LIBSSL cfg_get_integer(&ppg_ssl_port, grp, octstr_imm("ppg-ssl-port")); ssl_server_cert_file = cfg_get(grp, octstr_imm("ssl-server-cert-file")); ssl_server_key_file = cfg_get(grp, octstr_imm("ssl-server-key-file")); if (ppg_ssl_port != NO_HTTPS_PORT) { if (ssl_server_cert_file == NULL || ssl_server_key_file == NULL) panic(0, "cannot continue without server cert and/or key files"); use_global_server_certkey_file(ssl_server_cert_file, ssl_server_key_file); } octstr_destroy(ssl_server_cert_file); octstr_destroy(ssl_server_key_file);#endif /* If pi is trusted, ignore possible user groups. */ if (trusted_pi) { cfg_destroy(cfg); return USER_CONFIGURATION_ADDED; } /* But if it is not, we cannot continue without user groups.*/ if ((list = cfg_get_multi_group(cfg, octstr_imm("wap-push-user"))) == NULL) { panic(0, "No user group but ppg not trusted, stopping"); list_destroy(list, NULL); cfg_destroy(cfg); return USER_CONFIGURATION_NOT_ADDED; } if (!wap_push_ppg_pushuser_list_add(list, number_of_pushes, number_of_users)) { panic(0, "unable to create users configuration list, exiting"); return USER_CONFIGURATION_NOT_ADDED; } cfg_destroy(cfg); return USER_CONFIGURATION_ADDED;}static int ip_allowed_by_ppg(Octstr *ip){ if (ip == NULL) return 0; if (trusted_pi) return 1; if (ppg_deny_ip == NULL && ppg_allow_ip == NULL) { warning(0, "Your ppg core configuration lacks allowed and denied" " ip lists"); return 1; } if (ppg_deny_ip) if (octstr_compare(ppg_deny_ip, octstr_imm("*.*.*.*")) == 0) { panic(0, "Your ppg core configuration deny all ips, exiting"); return 0; } if (ppg_allow_ip) if (octstr_compare(ppg_allow_ip, octstr_imm("*.*.*.*")) == 0) { warning(0, "Your ppg core configuration allow all ips"); return 1; } if (ppg_deny_ip) if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(ppg_deny_ip, ip, octstr_imm(";"), octstr_imm("."))) { error(0, "ip found from denied list"); return 0; } if (ppg_allow_ip) if (wap_push_ppg_pushuser_search_ip_from_wildcarded_list(ppg_allow_ip, ip, octstr_imm(";"), octstr_imm("."))) { debug("wap.push.ppg.pushuser", 0, "PPG: ip_allowed_by_ppg: ip found" " from allowed list"); return 1; } warning(0, "did not found ip from any of core lists, deny it"); return 0;}/* * Event handling functions */static void ota_read_thread (void *arg){ WAPEvent *e; while (run_status == running && (e = list_consume(ppg_queue)) != NULL) { handle_internal_event(e); } }/* * Pap event functions handle only copy pointers. They do not allocate memory. */static PAPEvent *pap_event_create(Octstr *ip, Octstr *url, List *push_headers, Octstr *mime_content, List *cgivars, HTTPClient *client){ PAPEvent *p; p = gw_malloc(sizeof(PAPEvent)); p->ip = ip; p->url = url; p->push_headers = push_headers; p->mime_content = mime_content; p->cgivars = cgivars; p->client = client; return p;}static void pap_event_destroy(PAPEvent *p){ if (p == NULL) return; gw_free(p);}static void pap_event_destroy_item(void *p){ pap_event_destroy(p);}static void pap_event_unpack(PAPEvent *p, Octstr **ip, Octstr **url, List **push_headers, Octstr **mime_content, List **cgivars, HTTPClient **client){ *ip = p->ip; *url = p->url; *push_headers = p->push_headers; *mime_content = p->mime_content; *cgivars = p->cgivars; *client = p->client;}static void http_read_thread(void *arg){ PAPEvent *p; Octstr *ip; Octstr *url; List *push_headers; Octstr *mime_content; List *cgivars; HTTPClient *client; while (run_status == running) { client = http_accept_request(ppg_port, &ip, &url, &push_headers, &mime_content, &cgivars); if (client == NULL) break; p = pap_event_create(ip, url, push_headers, mime_content, cgivars, client); list_produce(pap_queue, p); }}#ifdef HAVE_LIBSSLstatic void https_read_thread(void *arg){ PAPEvent *p; Octstr *ip; Octstr *url; List *push_headers; Octstr *mime_content; List *cgivars; HTTPClient *client; while (run_status == running) { client = http_accept_request(ppg_ssl_port, &ip, &url, &push_headers, &mime_content, &cgivars); if (client == NULL) break; p = pap_event_create(ip, url, push_headers, mime_content, cgivars, client); list_produce(pap_queue, p); }}#endif/* * Authorization failure as such causes a challenge to the client (as required * by rfc 2617, chapter 1). * We store HTTPClient data structure corresponding a given push id, so that * we can send responses to the rigth address. * Pap chapter 14.4.1 states that we must return http status 202 after we have * accepted PAP message, even if it is unparsable. So only the non-existing * service error and some authorisation failures are handled at HTTP level. * When a phone number was unacceptable, we return a PAP level error, because * we cannot know this error before parsing the document. */static void pap_request_thread(void *arg){ WAPEvent *ppg_event; PAPEvent *p; size_t push_len; Octstr *pap_content, *push_data, *rdf_content, *mime_content, *plos, /* a temporary variable*/ *boundary, *content_header, /* Content-Type MIME header */ *url, *ip, *not_found, *username = NULL; int compiler_status, http_status; List *push_headers, /* MIME headers themselves */ *content_headers, /* Headers from the content entity, see pap chapters 8.2, 13.1. Rfc 2045 grammar calls these MIME-part-hea- ders */ *cgivars; HTTPClient *client; Octstr *dlr_url; http_status = 0; while (run_status == running && (p = list_consume(pap_queue)) != NULL) { http_status = HTTP_NOT_FOUND; pap_event_unpack(p, &ip, &url, &push_headers, &mime_content, &cgivars, &client); if (octstr_compare(url, ppg_url) != 0) { error(0, "Request <%s> from <%s>: service not found", octstr_get_cstr(url), octstr_get_cstr(ip));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -