📄 smsc_cimd2.c
字号:
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, "Retransmitting (take %d)", tries); goto retransmit; } warning(0, "Giving up."); goto io_error;}/* Close the SMSC socket without fanfare. */static void cimd2_close_socket(SMSCenter *smsc){ gw_assert(smsc != NULL); if (smsc->socket < 0) return; if (close(smsc->socket) < 0) warning(errno, "error closing CIMD2 socket"); smsc->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 cimd2_login(SMSCenter *smsc){ int ret; struct packet *packet = NULL; gw_assert(smsc != NULL); if (smsc->socket >= 0) { warning(0, "cimd2_login: socket was already open; closing"); cimd2_close_socket(smsc); } smsc->socket = tcpip_connect_to_server(octstr_get_cstr(smsc->cimd2_hostname), smsc->cimd2_port, NULL); /* XXX add interface_name if required */ if (smsc->socket == -1) goto error; packet = packet_create(LOGIN, BOGUS_SEQUENCE); packet_add_string_parm(packet, P_USER_IDENTITY, smsc->cimd2_username); packet_add_string_parm(packet, P_PASSWORD, smsc->cimd2_password); ret = cimd2_request(packet, smsc, NULL); if (ret < 0) goto error; packet_destroy(packet); info(0, "%s logged in.", smsc_name(smsc)); return 0;error: error(0, "cimd2_login failed"); cimd2_close_socket(smsc); packet_destroy(packet); return -1;}static void cimd2_logout(SMSCenter *smsc){ struct packet *packet = NULL; gw_assert(smsc != NULL); packet = packet_create(LOGOUT, BOGUS_SEQUENCE); /* TODO: Don't wait very long for a response in this case. */ cimd2_request(packet, smsc,NULL); packet_destroy(packet);}static int cimd2_send_alive(SMSCenter *smsc){ struct packet *packet = NULL; int ret; gw_assert(smsc != NULL); packet = packet_create(ALIVE, BOGUS_SEQUENCE); ret = cimd2_request(packet, smsc,NULL); packet_destroy(packet); if (ret < 0) warning(0, "CIMD2: SMSC not alive.\n"); return ret;}/***************************************************************************//* SMSC Interface, as defined in smsc_interface.def *//***************************************************************************/SMSCenter *cimd2_open(Octstr *hostname, int port, Octstr *username,Octstr *password, int keepalive, Octstr *sender_prefix){ SMSCenter *smsc = NULL; int maxlen; smsc = smscenter_construct(); gw_assert(smsc != NULL); smsc->type = SMSC_TYPE_CIMD2; smsc->keepalive = keepalive; smsc->cimd2_hostname = octstr_duplicate(hostname); smsc->cimd2_port = port; smsc->cimd2_username = octstr_duplicate(username); smsc->cimd2_password = octstr_duplicate(password); smsc->sender_prefix = octstr_duplicate(sender_prefix); sprintf(smsc->name, "CIMD2:%s:%d:%s", octstr_get_cstr(hostname), port, octstr_get_cstr(username)); smsc->cimd2_received = list_create(); smsc->cimd2_inbuffer = octstr_create(""); smsc->cimd2_error = 0; if (keepalive > 0) smsc->cimd2_next_ping = time(NULL) + keepalive * 60; maxlen = parm_maxlen(P_USER_IDENTITY); if (octstr_len(smsc->cimd2_username) > maxlen) { octstr_truncate(smsc->cimd2_username, maxlen); warning(0, "Truncating CIMD2 username to %d chars", maxlen); } maxlen = parm_maxlen(P_PASSWORD); if (octstr_len(smsc->cimd2_password) > maxlen) { octstr_truncate(smsc->cimd2_password, maxlen); warning(0, "Truncating CIMD2 password to %d chars", maxlen); } if (cimd2_login(smsc) < 0) goto error; return smsc;error: error(0, "cimd2_open failed"); smscenter_destruct(smsc); return NULL;}int cimd2_reopen(SMSCenter *smsc){ gw_assert(smsc != NULL); warning(0, "Attempting to re-open CIMD2 connection"); cimd2_close_socket(smsc); /* Restore message counters to their default values */ smsc->cimd2_send_seq = 1; smsc->cimd2_receive_seq = 0; /* Clear leftover input */ octstr_destroy(smsc->cimd2_inbuffer); smsc->cimd2_inbuffer = octstr_create(""); return cimd2_login(smsc);}int cimd2_close(SMSCenter *smsc){ int ret; int discarded; gw_assert(smsc != NULL); debug("bb.sms.cimd2", 0, "Closing CIMD2 SMSC"); if (smsc->socket < 0) { warning(0, "cimd2_close: already closed.\n"); return 0; } cimd2_logout(smsc); ret = close(smsc->socket); smsc->socket = -1; smsc->cimd2_send_seq = 0; smsc->cimd2_receive_seq = 1; octstr_destroy(smsc->cimd2_hostname); octstr_destroy(smsc->cimd2_username); octstr_destroy(smsc->cimd2_password); octstr_destroy(smsc->cimd2_inbuffer); discarded = list_len(smsc->cimd2_received); list_destroy(smsc->cimd2_received, msg_destroy_item); if (discarded > 0) warning(0, "CIMD2: discarded %d received messages", discarded); return ret;}int cimd2_submit_msg(SMSCenter *smsc, Msg *msg){ struct packet *packet; int ret = 0; int tries; Octstr *ts; ts = NULL; gw_assert(smsc != NULL); packet = packet_encode_message(msg, smsc->sender_prefix); if (!packet) return 0; /* We can't signal protocol errors yet */ for (tries = 0; tries < 3; tries++) { ret = cimd2_request(packet, smsc,&ts); if((ret == 0) && (ts) && (msg->sms.dlr_mask & 0x03)) { dlr_add(smsc->name, octstr_get_cstr(ts), octstr_get_cstr(msg->sms.sender), octstr_get_cstr(msg->sms.receiver), octstr_get_cstr(msg->sms.service), octstr_get_cstr(msg->sms.dlr_url), msg->sms.dlr_mask); octstr_destroy(ts); ts = NULL; } if (ret == 0 || ret == -1) break; if (cimd2_reopen(smsc) < 0) { ret = -1; break; } } packet_destroy(packet); return ret;}/* The bearerbox really doesn't like it if pending_smsmessage returns * an error code. We work around it until the bearerbox is rewritten. * Record the error here, and return it in cimd2_receive_msg. Return * "message available" if there is an error so that cimd2_receive_msg * is called. */int cimd2_pending_smsmessage(SMSCenter *smsc){ long ret; struct packet *packet; gw_assert(smsc != NULL); gw_assert(smsc->type == SMSC_TYPE_CIMD2); if (list_len(smsc->cimd2_received) > 0) return 1; if (smsc->socket < 0) { /* XXX We have to assume that smsc_send_message is * currently trying to reopen, so we have to make * this thread wait. It should be done in a nicer * way. */ return 0; } ret = read_available(smsc->socket, 0); if (ret == 0) { if (smsc->keepalive > 0 && smsc->cimd2_next_ping < time(NULL)) { if (cimd2_send_alive(smsc) < 0) { smsc->cimd2_error = 1; return 1; } } return 0; } if (ret < 0) { warning(errno, "cimd2_pending_smsmessage: read_available failed"); smsc->cimd2_error = 1; return 1; } /* We have some data waiting... see if it is an sms delivery. */ ret = octstr_append_from_socket(smsc->cimd2_inbuffer, smsc->socket); if (ret == 0) { warning(0, "cimd2_pending_smsmessage: service center closed connection."); smsc->cimd2_error = 1; return 1; } if (ret < 0) { warning(0, "cimd2_pending_smsmessage: read failed"); smsc->cimd2_error = 1; return 1; } for (;;) { packet = packet_extract(smsc->cimd2_inbuffer); if (!packet) break; packet_check(packet); packet_check_can_receive(packet); if (packet->operation < RESPONSE) cimd2_handle_request(packet, smsc); else { error(0, "cimd2_pending_smsmessage: unexpected response packet"); octstr_dump(packet->data, 0); } packet_destroy(packet); } if (list_len(smsc->cimd2_received) > 0) return 1; return 0;}int cimd2_receive_msg(SMSCenter *smsc, Msg **msg){ gw_assert(smsc != NULL); gw_assert(msg != NULL); if (smsc->cimd2_error) { smsc->cimd2_error = 0; return -1; } *msg = list_consume(smsc->cimd2_received); return 1;}static Msg *cimd2_accept_delivery_report_message(struct packet *request, SMSCenter *smsc){ Msg *msg = NULL; Octstr *destination = NULL; Octstr *timestamp = NULL; Octstr *statuscode = NULL; int st_code; int code; destination = packet_get_parm(request, P_DESTINATION_ADDRESS); timestamp = packet_get_parm(request, P_MC_TIMESTAMP); statuscode = packet_get_parm(request, P_STATUS_CODE); st_code = atoi(octstr_get_cstr(statuscode)); switch(st_code) { case 2: /* validity period expired */ case 3: /* delivery failed */ code = DLR_FAIL; break; case 4: /* delivery successful */ code = DLR_SUCCESS; break; default: code = 0; } if(code) msg = dlr_find(smsc->name, octstr_get_cstr(timestamp), octstr_get_cstr(destination), code); else msg = NULL; octstr_destroy(statuscode); octstr_destroy(destination); octstr_destroy(timestamp); /* recode the body into msgdata */ if (msg) { msg->sms.msgdata = packet_get_parm(request, P_USER_DATA); } return msg; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -