📄 smsc_oisd.c
字号:
* the recipient in interpreting the SM. * z = reply path * y = user data header indicator * x = reserved */ /* * Destination addr. and Originating addr. w/o TOA */ /* Destination addr. length */ dest_len = octstr_get_char(request->data, 10); /* Destination addr. */ msg->sms.receiver = octstr_copy(request->data, 11+2, dest_len-2); /* Originating addr. length */ origin_len = octstr_get_char(request->data, 11+dest_len+4); /* Originating addr. */ msg->sms.sender = octstr_copy(request->data, 11+dest_len+5+2, origin_len-2); DCS = octstr_get_char(request->data, 11+dest_len+5+origin_len); if (!dcs_to_fields(&msg, DCS)) { /* XXX: Should reject this message ? */ debug("bb.sms.oisd", 0, "OISD[%s]: Invalid DCS", octstr_get_cstr(conn->id)); dcs_to_fields(&msg, 0); } add_info = octstr_get_char(request->data,11+dest_len+5+origin_len+2); msglen7 = octstr_get_char(request->data, 11+dest_len+5+origin_len+3); msglen8 = octstr_get_char(request->data, 11+dest_len+5+origin_len+4); msg->sms.rpi = add_info & 0x01; debug("bb.sms.oisd", 0, "OISD[%s]: received DCS=%02X, add_info=%d, msglen7=%d, msglen8=%d, rpi=%ld", octstr_get_cstr(conn->id), DCS, add_info, msglen7, msglen8, msg->sms.rpi); if (msg->sms.coding == DC_7BIT) { msg->sms.msgdata = oisd_expand_gsm7(octstr_copy(request->data, 11+dest_len+5+origin_len+5, msglen7)); debug("bb.sms.oisd", 0, "OISD[%s]: received raw8=%s ", octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.msgdata)); if (add_info & 0x02) { warning(0, "OISD[%s]: 7-bit UDH ?", octstr_get_cstr(conn->id)); } else { charset_gsm_to_latin1(msg->sms.msgdata); debug("bb.sms.oisd", 0, "OISD[%s]: received latin1=%s", octstr_get_cstr(conn->id), octstr_get_cstr(msg->sms.msgdata)); } } else { /* 0xf4, 0xf5, 0xf6, 0xf7; 8bit to disp, mem, sim or term */ if (add_info & 0x02) { udh_len = octstr_get_char(request->data, 11+dest_len+5+origin_len+5)+1; msg->sms.msgdata = octstr_copy(request->data, 11+dest_len+5+origin_len+5+udh_len, msglen8); msg->sms.udhdata = octstr_copy(request->data, 11+dest_len+5+origin_len+5, udh_len); } else { msg->sms.msgdata = octstr_copy(request->data, 11+dest_len+5+origin_len+5, msglen8); } } /* Code elsewhere in the gateway always expects the sender and * receiver fields to be filled, so we discard messages that * lack them. If they should not be discarded, then the code * handling sms messages should be reviewed. -- RB */ if (!(msg->sms.receiver) || octstr_len(msg->sms.receiver) == 0) { info(0, "OISD[%s]: Got SMS without receiver, discarding.", octstr_get_cstr(conn->id)); goto error; } if (!(msg->sms.sender) || octstr_len(msg->sms.sender) == 0) { info(0, "OISD[%s]: Got SMS without sender, discarding.", octstr_get_cstr(conn->id)); goto error; } if ((!(msg->sms.msgdata) || octstr_len(msg->sms.msgdata) == 0) && (!(msg->sms.udhdata) || octstr_len(msg->sms.udhdata) == 0)) { info(0, "OISD[%s]: Got empty SMS, ignoring.", octstr_get_cstr(conn->id)); goto error; } return msg;error: msg_destroy(msg); return NULL;}/* Deal with a request from the OISD server, and acknowledge it. */static void oisd_handle_request(struct packet *request, SMSCConn *conn){ PrivData *pdata = conn->data; Msg *msg = NULL; if (request->operation == STATUS_REPORT) { msg = oisd_accept_delivery_report_message(request, conn); if (msg) list_append(pdata->received, msg); } else if (request->operation == DELIVER_SM) { msg = oisd_accept_message(request, conn); if (msg) list_append(pdata->received, msg); } oisd_send_response(request, pdata);}/* Send a request and wait for the ack. If the other side responds with * an error code, attempt to correct and retry. * If other packets arrive while we wait for the ack, handle them. * * Return -1 if the SMSC refused the request. Return -2 for other * errors, such as being unable to send the request at all. If the * function returns -2, the caller would do well to try to reopen the * connection. * * The SMSCenter must be already open. */static int oisd_request(struct packet *request, SMSCConn *conn, Octstr **ts){ PrivData *pdata = conn->data; int ret; struct packet *reply = NULL; int errorcode; int tries = 0; Octstr *request_name; gw_assert(pdata != NULL); gw_assert(request != NULL); gw_assert(operation_can_send(request->operation)); if (pdata->socket < 0) { warning(0, "OISD[%s]: oisd_request: socket not open.", octstr_get_cstr(conn->id)); return -2; } packet_set_data_size(request);retransmit: packet_set_send_sequence(request, pdata); request_name = operation_name(request->operation); debug("bb.sms.oisd", 0, "OISD[%s]: sending %s request", octstr_get_cstr(conn->id), octstr_get_cstr(request_name)); octstr_destroy(request_name); if (request->operation != RETRIEVE_REQUEST) octstr_dump(request->data, 0); ret = octstr_write_to_socket(pdata->socket, request->data); if (ret < 0) goto io_error;next_reply: packet_destroy(reply); /* destroy old, if any */ reply = oisd_get_packet(pdata, ts); if (!reply) goto io_error; /* The server sent us a request. Handle it, then wait for * a new reply. */ if (reply->operation < RESPONSE) { oisd_handle_request(reply, conn); goto next_reply; } if (reply->opref != request->opref) { /* We got a response to a different request number than * what we send. Strange. */ warning(0, "OISD[%s]: response had unexpected sequence number; ignoring.", octstr_get_cstr(conn->id)); goto next_reply; } if (reply->operation != request->operation + RESPONSE) { /* We got a response that didn't match our request */ Octstr *request_name = operation_name(request->operation); Octstr *reply_name = operation_name(reply->operation); warning(0, "OISD[%s]: %s request got a %s", octstr_get_cstr(conn->id), octstr_get_cstr(request_name), octstr_get_cstr(reply_name)); octstr_destroy(request_name); octstr_destroy(reply_name); octstr_dump(reply->data, 0); goto retry; } errorcode = octstr_get_char(reply->data, 10); /* Result */ if (errorcode > 0) goto error; /* The reply passed all the checks... looks like the SMSC accepted * our request! */ packet_destroy(reply); return 0;io_error: packet_destroy(reply); return -2;error: packet_destroy(reply); return -1;retry: if (++tries < 3) { warning(0, "OISD[%s]: Retransmitting (take %d)", octstr_get_cstr(conn->id), tries); goto retransmit; } warning(0, "OISD[%s]: Giving up.", octstr_get_cstr(conn->id)); goto io_error;}/* Close the SMSC socket without fanfare. */static void oisd_close_socket(PrivData *pdata){ gw_assert(pdata != NULL); if (pdata->socket < 0) return; if (close(pdata->socket) < 0) warning(errno, "OISD[%s]: error closing socket", octstr_get_cstr(pdata->conn->id)); pdata->socket = -1;}/* * Open a socket to the SMSC, send a login packet, and wait for ack. * This may block. Return 0 for success, or -1 for failure. * Make sure the socket is closed before calling this function, otherwise * we will leak fd's. */static int oisd_login(SMSCConn *conn){ PrivData *pdata = conn->data; struct packet *packet = NULL; gw_assert(pdata != NULL); if (pdata->socket >= 0) { warning(0, "OISD[%s]: login: socket was already open; closing", octstr_get_cstr(conn->id)); oisd_close_socket(pdata); } pdata->socket = tcpip_connect_to_server( octstr_get_cstr(pdata->host), pdata->port, (conn->our_host ? octstr_get_cstr(conn->our_host) : NULL)); if (pdata->socket != -1) { info(0, "OISD[%s] logged in.", octstr_get_cstr(conn->id)); return 0; } error(0, "OISD[%s] login failed.", octstr_get_cstr(conn->id)); oisd_close_socket(pdata); packet_destroy(packet); return -1;}static int oisd_send_delivery_request(SMSCConn *conn){ PrivData *pdata = conn->data; struct packet *packet = NULL; int ret; gw_assert(conn != NULL); packet = packet_create(RETRIEVE_REQUEST, BOGUS_SEQUENCE); gw_assert(octstr_check_range(pdata->my_number, 0, octstr_len(pdata->my_number), isphonedigit)); /* Originating address length */ octstr_append_char(packet->data, (char) (octstr_len(pdata->my_number) + 2)); /* TON */ octstr_append_char(packet->data, 0x42); /* NPI */ octstr_append_char(packet->data, 0x44); /* Originating address */ octstr_append(packet->data, pdata->my_number); /* Receive ready flag */ octstr_append_char(packet->data, 1); /* Retrieve order */ octstr_append_char(packet->data, 0); ret = oisd_request(packet, conn, NULL); packet_destroy(packet); if (ret < 0) warning(0, "OISD[%s]: Sending delivery request failed.\n", octstr_get_cstr(conn->id)); return ret;}static void oisd_destroy(PrivData *pdata){ int discarded; if (pdata == NULL) return; octstr_destroy(pdata->host); octstr_destroy(pdata->inbuffer); octstr_destroy(pdata->my_number); discarded = list_len(pdata->received); if (discarded > 0) warning(0, "OISD[%s]: discarded %d received messages", octstr_get_cstr(pdata->conn->id), discarded); list_destroy(pdata->received, msg_destroy_item); list_destroy(pdata->outgoing_queue, NULL); list_destroy(pdata->stopped, NULL); gw_free(pdata);}static int oisd_submit_msg(SMSCConn *conn, Msg *msg){ PrivData *pdata = conn->data; struct packet *packet; Octstr *ts = NULL; int ret; gw_assert(pdata != NULL); debug("bb.sms.oisd", 0, "OISD[%s]: sending message", octstr_get_cstr(conn->id)); packet = packet_encode_message(msg, conn); if (!packet) { /* This is a protocol error. Does this help? I doubt.. * But nevermind that. */ bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_MALFORMED, octstr_create("MALFORMED")); return -1; } ret = oisd_request(packet, conn, &ts); if((ret == 0) && (ts) && DLR_IS_SUCCESS_OR_FAIL(msg->sms.dlr_mask) && !pdata->no_dlr) { dlr_add(conn->name, ts, msg); } octstr_destroy(ts); packet_destroy(packet); if (ret == -1) { bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_REJECTED, octstr_create("REJECTED")); } else if (ret == -2) { oisd_close_socket(pdata); bb_smscconn_send_failed(conn, msg, SMSCCONN_FAILED_TEMPORARILY, NULL); mutex_lock(conn->flow_mutex); conn->status = SMSCCONN_DISCONNECTED; mutex_unlock(conn->flow_mutex); } else { bb_smscconn_sent(conn, msg, NULL); } return ret;}static int oisd_receive_msg(SMSCConn *conn, Msg **msg)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -