#include "opnetProtoSimProcess.h"
#include "mgen.h"
extern "C"
{
#include "oms_pr.h"
#include "udp_api.h"
#include "ip_addr_v4.h"
#include "ip_rte_v4.h"
}
OpnetProtoSimProcess::OpnetProtoSimProcess()
{
}
OpnetProtoSimProcess::~OpnetProtoSimProcess(void)
{
}
ProtoSimAgent::SocketProxy* OpnetProtoSimProcess::OpenSocket(ProtoSocket& theSocket)
{
#ifdef OP_DEBUG1
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::OpenSocket() with udp_id = %d\n",
udp_process_id);
#endif
UdpSocketProxy* udpProxy;
TcpSocketProxy* tcpProxy;
if (theSocket.GetProtocol() == theSocket.TCP)
{
tcpProxy = new TcpSocketProxy(this);
if (tcpProxy)
{
tcpProxy->AttachSocket(theSocket);
socket_proxy_list.Prepend(*tcpProxy);
return tcpProxy;
}
else
{
fprintf(stderr, "OpnetProtoSimProcess::OpenSocket() new SocketAgent error\n");
return NULL;
}
}
else
{
udpProxy = new UdpSocketProxy(this); if (udpProxy)
{
udpProxy->AttachSocket(theSocket);
socket_proxy_list.Prepend(*udpProxy);
return udpProxy;
}
else
{
fprintf(stderr, "OpnetProtoSimProcess::OpenSocket() new SocketAgent error\n");
return NULL;
}
}
}
void OpnetProtoSimProcess::CloseSocket(ProtoSocket& theSocket)
{
#ifdef OP_DEBUG1
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::CloseSocket()\n");
#endif
SocketProxy* socketProxy = static_cast<SocketProxy*>(theSocket.GetHandle());
if (theSocket.GetProtocol() == theSocket.TCP)
{
ApiT_Tcp_App_Handle hndl = *(((TcpSocketProxy*)socketProxy)->sim_process->GetTcpHandle());
tcp_connection_close(hndl);
}
socket_proxy_list.Remove(*socketProxy);
}
void OpnetProtoSimProcess::OnReceive(int strm_indx) {
#ifdef OP_DEBUG1
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::OnReceive()\n");
#endif
Ici* iciPtr = op_intrpt_ici();
if (OPC_NIL != iciPtr)
{
int localPort;
int connId;
char iciformat[32];
op_ici_format(iciPtr,iciformat);
if (!strcmp(iciformat,"tcp_status_ind"))
{
op_ici_attr_get(iciPtr, "conn_id", &connId);
SocketProxy* socketProxy = socket_proxy_list.FindProxyByConn(connId);
if (socketProxy)
{
Packet* pkt = op_pk_get(strm_indx);
ReceivePacketMonitor(iciPtr, pkt);
char* recvData;
op_pk_fd_get(pkt, 0, &recvData);
unsigned int recvLen = op_pk_bulk_size_get(pkt) / 8;
ProtoAddress srcAddr;
ProtoAddress dstAddr;
static_cast<TcpSocketProxy*>(socketProxy)->OnReceive(recvData, recvLen, srcAddr, dstAddr);
op_prg_mem_free(recvData);
op_pk_destroy(pkt);
}
}
else if (!strcmp(iciformat,"udp_command_v3"))
{
op_ici_attr_get(iciPtr, "local_port", &localPort);
SocketProxy* socketProxy = socket_proxy_list.FindProxyByPort(localPort);
if (socketProxy)
{
Packet* pkt = op_pk_get(strm_indx);
ReceivePacketMonitor(iciPtr, pkt);
char* recvData;
op_pk_fd_get(pkt, 0, &recvData);
int recvLen = op_pk_bulk_size_get(pkt) / 8;
IpT_Address remoteAddr;
op_ici_attr_get(iciPtr, "rem_addr", &remoteAddr);
int remotePort;
op_ici_attr_get(iciPtr, "rem_port", &remotePort);
IpT_Address localAddr;
op_ici_attr_get(iciPtr, "src_addr", &localAddr);
#ifdef OP_DEBUG1
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::OnReceive() - remoteAdd - %u, localAdrr = %u, rec_lgn = %d\n",
remoteAddr, localAddr, recvLen);
#endif
ProtoAddress srcAddr;
srcAddr.SimSetAddress(remoteAddr);
srcAddr.SetPort(remotePort);
ProtoAddress dstAddr;
dstAddr.SimSetAddress(localAddr);
dstAddr.SetPort(localPort);
static_cast<UdpSocketProxy*>(socketProxy)->OnReceive(recvData, recvLen, srcAddr, dstAddr);
op_prg_mem_free(recvData);
op_pk_destroy(pkt);
}
}
else if (!strcmp(iciformat,"sink_command"))
{
Packet* pkt = op_pk_get(strm_indx);
ReceivePacketMonitor(iciPtr, pkt);
char* recvData;
op_pk_fd_get(pkt, 0, &recvData);
int recvLen = op_pk_bulk_size_get(pkt) / 8;
IpT_Address remoteAddr;
op_ici_attr_get(iciPtr, "rem_addr", &remoteAddr);
int remotePort;
op_ici_attr_get(iciPtr, "rem_port", &remotePort);
IpT_Address localAddr;
op_ici_attr_get(iciPtr, "src_addr", &localAddr);
#ifdef OP_DEBUG1
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::OnReceive() - remoteAdd - %u, localAdrr = %u, rec_lgn = %d\n",
remoteAddr, localAddr, recvLen);
#endif
ProtoAddress srcAddr;
srcAddr.SimSetAddress(remoteAddr);
srcAddr.SetPort(remotePort);
ProtoAddress dstAddr;
dstAddr.SimSetAddress(localAddr);
dstAddr.SetPort(localPort);
HandleMgenMessage(recvData,recvLen,srcAddr);
op_prg_mem_free(recvData);
op_pk_destroy(pkt);
}
else
{
op_sim_end ("Error: DoReceive() Unrecognized ici format", "", "", "");
}
}
else
{
op_sim_end ("Error: DoReceive() OPC_NIL cmd", "", "", "");
}
}
OpnetProtoSimProcess::UdpSocketProxy::UdpSocketProxy(OpnetProtoSimProcess* simProcess) : sim_process(simProcess),
mcast_ttl(255), mcast_loopback(false),
recv_data(NULL), recv_data_len(0), udp_command_ici(NULL)
{
#ifdef OP_DEBUG2
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::UdpSocketProxy::UdpSocketProxy(udpId = %ld)\n",
udpProcessId);
#endif
}
OpnetProtoSimProcess::UdpSocketProxy::~UdpSocketProxy()
{
op_ici_destroy (udp_command_ici);
}
bool OpnetProtoSimProcess::UdpSocketProxy::Bind(UINT16& thePort)
{
#ifdef OP_DEBUG1
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::UdpSocketProxy::Bind, udp_process_id = %d)\n",
sim_process->udp_process_id);
#endif
udp_command_ici = op_ici_create("udp_command_v3");
op_ici_attr_set(udp_command_ici, "local_port", (int)thePort);
op_ici_install(udp_command_ici);
op_intrpt_force_remote(UDPC_COMMAND_CREATE_PORT, sim_process->GetUdpProcId()); return true;
}
bool OpnetProtoSimProcess::UdpSocketProxy::SendTo(const char* buffer,
unsigned int& buflen,
const ProtoAddress& dstAddr)
{
#ifdef OP_DEBUG1
printf("\tOpnetProtoSimProcess::UdpSocketProxy::SendTo: local_port %d, rem_port %d, rem_addr_%u\n",
proto_socket->GetPort(), dstAddr.GetPort(), dstAddr.SimGetAddress()); #endif
Packet* pkt = op_pk_create(buflen*8);
char* payload = (char*) op_prg_mem_copy_create((void*)buffer, buflen);
op_pk_fd_set(pkt, 0, OPC_FIELD_TYPE_STRUCT, payload, 0,
op_prg_mem_copy_create, op_prg_mem_free, buflen);
op_ici_attr_set(udp_command_ici, "local_port", proto_socket->GetPort());
op_ici_attr_set(udp_command_ici, "rem_port", dstAddr.GetPort());
op_ici_attr_set(udp_command_ici, "rem_addr", dstAddr.SimGetAddress());
op_ici_install(udp_command_ici);
sim_process->TransmitPacketMonitor(udp_command_ici, pkt);
op_pk_send_forced(pkt, 0);
return true;
}
bool OpnetProtoSimProcess::UdpSocketProxy::RecvFrom(char* buffer,
unsigned int& numBytes,
ProtoAddress& srcAddr)
{
#ifdef OP_DEBUG1
printf("\tOpnetProtoSimProcess::UdpSocketProxy::RecvFrom\n");
#endif
if (recv_data)
{
if (numBytes >= recv_data_len)
{
numBytes = recv_data_len;
memcpy(buffer, recv_data, numBytes);
op_prg_mem_free (recv_data); srcAddr = src_addr;
recv_data = NULL;
recv_data_len = 0;
return true;
}
else
{
PLOG(PL_ERROR, "OpnetProtoSimProcess::UdpSocketProxy::RecvFrom buffer too small\n");
numBytes = 0;
return false;
}
}
else
{
PLOG(PL_WARN, "OpnetProtoSimProcess::UdpSocketProxy::RecvFrom no data ready\n");
numBytes = 0;
return false;
}
}
bool OpnetProtoSimProcess::UdpSocketProxy::JoinGroup(const ProtoAddress& groupAddr)
{
return true;
}
bool OpnetProtoSimProcess::UdpSocketProxy::LeaveGroup(const ProtoAddress& groupAddr)
{
return true;
}
void OpnetProtoSimProcess::UdpSocketProxy::OnReceive(char* recvData,
unsigned int recvLen,
const ProtoAddress& srcAddr,
const ProtoAddress& dstAddr)
{
#ifdef OP_DEBUG1
printf("\tOpnetProtoSimProcess::UdpSocketProxy::OnReceive - RecvLen = %u\n", recvLen); #endif
recv_data = (char*) op_prg_mem_copy_create((void*)recvData, recvLen);
recv_data_len = recvLen;
src_addr = srcAddr;
if (proto_socket)
proto_socket->OnNotify(ProtoSocket::NOTIFY_INPUT);
}
OpnetProtoSimProcess::TcpSocketProxy::TcpSocketProxy(OpnetProtoSimProcess* simProcess)
: sim_process(simProcess),
recv_data(NULL), recv_data_len(0), tcp_command_ici(NULL)
{
#ifdef OP_DEBUG2
printf("\topnetProtosimProcess.pr.c - OpnetProtoSimProcess::TcpSocketProxy::TcpSocketProxy()\n");
#endif
}
OpnetProtoSimProcess::TcpSocketProxy::~TcpSocketProxy()
{
op_ici_destroy (tcp_command_ici);
}
bool OpnetProtoSimProcess::TcpSocketProxy::Bind(UINT16& thePort)
{
local_port = thePort;
return true;
}
bool OpnetProtoSimProcess::TcpSocketProxy::Connect(const ProtoAddress& dstAddr)
{
ApiT_Tcp_App_Handle* hndl_ptr = sim_process->GetTcpHandle();
IpT_Address rem_addr = dstAddr.SimGetAddress();
TcpT_Port rem_port = GetPort(); IpT_Address local_addr = GetTcpHostAddress().SimGetAddress();
TcpT_Port loc_port = GetPort();
int command = TCPC_COMMAND_OPEN_ACTIVE;
int ip_qos = 0;
int tcp_conn_id =
tcp_connection_with_source_open (hndl_ptr, rem_addr, rem_port, local_addr, loc_port, command, ip_qos);
if (tcp_conn_id == TCPC_CONN_ID_INVALID)
return false;
else
{
proto_socket->SetState(ProtoSocket::CONNECTED);
conn_id = tcp_conn_id;
return true;
}
}
bool OpnetProtoSimProcess::TcpSocketProxy::Accept(ProtoSocket* theSocket)
{
theSocket->GetDestination() = GetTcpRemAddress(); ProtoSocket* socket = GetSocket();
socket->GetDestination() = GetTcpRemAddress(); return true;
}
bool OpnetProtoSimProcess::TcpSocketProxy::Listen(UINT16 thePort)
{
ApiT_Tcp_App_Handle* hndl_ptr = sim_process->GetTcpHandle();
IpT_Address rem_addr = 0;
TcpT_Port rem_port = TCPC_PORT_UNSPEC;
IpT_Address local_addr = GetTcpHostAddress().SimGetAddress();
TcpT_Port loc_port = GetPort();
int command = TCPC_COMMAND_OPEN_PASSIVE;
int ip_qos = 0;
int tcp_conn_id =
tcp_connection_with_source_open (hndl_ptr, rem_addr, rem_port, local_addr, loc_port, command, ip_qos);
if (tcp_conn_id == TCPC_CONN_ID_INVALID)
return false;
else
{
tcp_receive_command_send(*hndl_ptr,1);
conn_id = tcp_conn_id;
return true;
}
}
bool OpnetProtoSimProcess::TcpSocketProxy::SendTo(const char* buffer,
unsigned int& buflen,
const ProtoAddress& dstAddr)
{
ApiT_Tcp_App_Handle* hndl_ptr = sim_process->GetTcpHandle();
Packet* pkt = op_pk_create(buflen*8);
char* payload = (char*) op_prg_mem_copy_create((void*)buffer, buflen);
op_pk_fd_set(pkt, 0, OPC_FIELD_TYPE_STRUCT, payload, 0,
op_prg_mem_copy_create, op_prg_mem_free, buflen);
Ici* dummy_ici;
sim_process->TransmitPacketMonitor(dummy_ici, pkt); tcp_data_send(*hndl_ptr,pkt);
return true;
}
bool OpnetProtoSimProcess::TcpSocketProxy::Send(const char* buffer,
unsigned int& numBytes)
{
return false;
}
bool OpnetProtoSimProcess::TcpSocketProxy::RecvFrom(char* buffer,
unsigned int& numBytes,
ProtoAddress& srcAddr)
{
if (recv_data)
{
if (numBytes >= recv_data_len)
{
numBytes = recv_data_len;
memcpy(buffer, recv_data, numBytes);
op_prg_mem_free (recv_data);
srcAddr = src_addr;
recv_data = NULL;
recv_data_len = 0;
return true;
}
else
{
PLOG(PL_ERROR, "OpnetProtoSimProcess::TcpSocketProxy::RecvFrom buffer too small\n");
numBytes = 0;
return false;
}
}
else
{
PLOG(PL_WARN, "OpnetProtoSimProcess::TcpSocketProxy::RecvFrom no data ready\n");
numBytes = 0;
return false;
}
}
bool OpnetProtoSimProcess::TcpSocketProxy::Recv(char* buffer,
unsigned int& numBytes)
{
ApiT_Tcp_App_Handle* hndl_ptr = sim_process->GetTcpHandle();
tcp_receive_command_send(*hndl_ptr,1);
recv_data = (char*) op_prg_mem_copy_create((void*)buffer, numBytes);
recv_data_len = numBytes;
if (proto_socket)
proto_socket->OnNotify(ProtoSocket::NOTIFY_INPUT);
return true;
}
void OpnetProtoSimProcess::TcpSocketProxy::OnReceive(char* recvData,
unsigned int recvLen,
const ProtoAddress& srcAddr,
const ProtoAddress& dstAddr)
{
ApiT_Tcp_App_Handle* hndl_ptr = sim_process->GetTcpHandle();
tcp_receive_command_send(*hndl_ptr,1);
recv_data = (char*) op_prg_mem_copy_create((void*)recvData, recvLen);
recv_data_len = recvLen;
src_addr = srcAddr;
if (proto_socket)
proto_socket->OnNotify(ProtoSocket::NOTIFY_INPUT);
}
bool OpnetProtoSimProcess::TcpSocketProxy::JoinGroup(const ProtoAddress& groupAddr)
{
return true;
}
bool OpnetProtoSimProcess::TcpSocketProxy::LeaveGroup(const ProtoAddress& groupAddr)
{
return true;
}
ProtoSimAgent::SocketProxy* OpnetProtoSimProcess::TcpSocketProxy::TcpSockList::FindProxyByConn(int connId)
{
TcpSocketProxy* next = (TcpSocketProxy*)SocketProxy::List::head;
while (next)
{
if (next->GetConn() == connId)
return (SocketProxy*)next;
else
next = (TcpSocketProxy*)next->GetNext();
}
return NULL;
}