view smpp-trx-sa/tcpconn.c @ 255:b0bf167bb846

themwi-update-outrt: add route-to-e911 option
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 15 Aug 2023 00:23:03 -0800
parents 9d6e8d99d2b1
children 1bf989f60aa3
line wrap: on
line source

/*
 * This module implements the part of smpp-trx-sa that handles
 * the TCP connection to the SMPP server.
 */

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>

extern FILE *logF;

int tcpsock;

static u_char rx_buf[0x10000];
static unsigned rx_accum, rx_pdu_len;
static int rx_body;

void
open_tcp_conn(server_sin)
	struct sockaddr_in *server_sin;
{
	int rc;

	tcpsock = socket(AF_INET, SOCK_STREAM, 0);
	if (tcpsock < 0) {
		perror("socket(AF_INET, SOCK_STREAM, 0)");
		exit(1);
	}
	rc = connect(tcpsock, (struct sockaddr *) server_sin,
		     sizeof(struct sockaddr_in));
	if (rc < 0) {
		perror("TCP connect");
		exit(1);
	}
}

static void
got_full_pdu()
{
	unsigned command_id;

	/* prepare for next PDU Rx */
	rx_body = 0;
	rx_accum = 0;
	/* back to the one we just got */
	command_id = (rx_buf[4] << 24) | (rx_buf[5] << 16) | (rx_buf[6] << 8) |
		     rx_buf[7];
	if (command_id == 0x15 && rx_pdu_len == 16) {
		send_enq_link_resp(rx_buf);
		return;
	}
	log_rx_pdu(rx_buf, rx_pdu_len);
	if (command_id == 0x05 || command_id == 0x103)
		send_message_resp(rx_buf);
}

void
tcpsock_select_handler()
{
	unsigned goal;
	int cc;

	if (rx_body)
		goal = rx_pdu_len;
	else
		goal = 16;
	cc = read(tcpsock, rx_buf + rx_accum, goal - rx_accum);
	if (cc < 0) {
		perror("read from TCP socket");
		log_fatal_error("error reading from TCP socket");
		exit(1);
	}
	if (cc == 0) {
		log_fatal_error("Server closed TCP connection");
		exit(1);
	}
	rx_accum += cc;
	if (rx_accum < goal)
		return;
	if (rx_body) {
		got_full_pdu();
		return;
	}
	if (rx_buf[0] || rx_buf[1]) {
		log_rx_pdu(rx_buf, 16);
		fprintf(logF, "Fatal error: length exceeds limit\n");
		exit(1);
	}
	rx_pdu_len = (rx_buf[2] << 8) | rx_buf[3];
	if (rx_pdu_len < 16) {
		log_rx_pdu(rx_buf, 16);
		fprintf(logF, "Fatal error: length below 16\n");
		exit(1);
	}
	if (rx_pdu_len == 16) {
		got_full_pdu();
		return;
	}
	rx_body = 1;
}