mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-21 14:55:57 -06:00
1051 lines
27 KiB
C++
1051 lines
27 KiB
C++
/***************************************************************************
|
|
main - description
|
|
-------------------
|
|
begin : Aug. 2, 2007
|
|
copyright : (C) 2007 by Allen
|
|
email : bon_ami_@hotmail.com
|
|
***************************************************************************/
|
|
|
|
/***************************************************************************
|
|
* *
|
|
* Explicit Distribution Limitation *
|
|
* This rule overrides others below. *
|
|
* This program may not be modified or used by, or, if possible, *
|
|
* redistributed to people described as below, *
|
|
* 1.Japanese who hold hostility against Chinese. *
|
|
* 2.or, those who discriminate against people based solely on race, *
|
|
* gender or sexual orientation. *
|
|
* *
|
|
***************************************************************************/
|
|
/***************************************************************************
|
|
* *
|
|
* This program is free software; you can redistribute it and/or modify *
|
|
* it under the terms of the GNU General Public License as published by *
|
|
* the Free Software Foundation; either version 2 of the License, or *
|
|
* (at your option) any later version. *
|
|
* *
|
|
***************************************************************************/
|
|
/*
|
|
* source code of EZ Comm Project Ultimate++ functionalities
|
|
*/
|
|
|
|
#include "main.h"
|
|
|
|
#include "time.h"
|
|
|
|
#define IMAGEFILE <ezcomm/ezcomm.iml>
|
|
#include <Draw/iml_source.h>
|
|
|
|
bool ezcommwin::HotKey(dword key)
|
|
{
|
|
switch (key)
|
|
{
|
|
case K_ENTER:
|
|
case K_CTRL_ENTER:
|
|
Butt_out();
|
|
return true;
|
|
}
|
|
return TopWindow::HotKey(key);
|
|
}
|
|
|
|
void ezcommwin::kill_all(void)
|
|
{
|
|
std::list<ezproject::ezComm*>::iterator pos;
|
|
|
|
for (pos = ezcomm.begin(); pos != ezcomm.end(); pos++)
|
|
{
|
|
(*pos)->disconnect();
|
|
/* thread must release *pos */
|
|
}
|
|
}
|
|
|
|
void ezcommwin::WClose()
|
|
{
|
|
/* validate controls */
|
|
port_rmt.Clear();
|
|
port_lcl.Clear();
|
|
|
|
/* resource release */
|
|
kill_all();
|
|
WSACleanup();
|
|
|
|
/* go on termination */
|
|
Close();
|
|
}
|
|
|
|
using namespace ezproject;
|
|
|
|
ezcommwin::ezcommwin()
|
|
{
|
|
/* interface */
|
|
CtrlLayout(*this, "EZ Comm");
|
|
Icon(IMAGECLASS::Get("ico"), IMAGECLASS::Get("ico"));
|
|
arr_r.SetImage(IMAGECLASS::Get("arrow_r"));
|
|
arr_l.SetImage(IMAGECLASS::Get("arrow_l"));
|
|
arr_o.SetImage(IMAGECLASS::Get("arrow_r"));
|
|
arr_i.SetImage(IMAGECLASS::Get("arrow_l"));
|
|
port_rmt.Min(1);
|
|
port_rmt.Max(65535);
|
|
port_lcl.Min(1);
|
|
port_lcl.Max(65535);
|
|
comm_type.Set(0, COMM_TYPE_UDP, "UDP");
|
|
comm_type.Set(1, COMM_TYPE_TCP, "TCP");
|
|
hist_addr_in.Hide();
|
|
hist_addr_in.SetDropLines(HIST_SOCK_DROP_NUM);
|
|
comm_type.Tip("select communication method");
|
|
msg.Add("Have a nice day.");
|
|
msg.Add("Bonjour.");
|
|
msg.Add("Salut");
|
|
msg.Add("hallo");
|
|
msg.Add("ciao");
|
|
msg.Add("hola");
|
|
msg.Add("written by Allen");
|
|
msg.Add("a sub-project of EZ Project");
|
|
msg.Add("http://ezproject.sourceforge.net/");
|
|
msg.Add("Windows or Linux, Text or Graphical.");
|
|
msg.Add("Anti-Discrimination");
|
|
msg.Add("cannot be used by Japanese who hold hostility against Chinese");
|
|
msg.Add("cannot be used by those who have race discrimination");
|
|
msg.Add("cannot be used by those who have gender discrimination");
|
|
msg.Add("cannot be used by those who have sexual orientation discrimination");
|
|
info.NoSb();
|
|
disp(ezoi::OILVL_NA, "under GPL with\n a couple of exception rules");
|
|
changes = 0;
|
|
max_key = 0;
|
|
|
|
ip_rmt.SetData("192.168.4.176");
|
|
port_rmt.SetData(5070);
|
|
port_lcl.SetData(5060);
|
|
text_out.SetData("testing 123");
|
|
|
|
/* callbacks */
|
|
ip_rmt <<= THISBACK(Ip_rmt);
|
|
port_rmt <<= THISBACK(Port_rmt);
|
|
hist_text_in <<= THISBACK(Hist_text_in);
|
|
port_lcl <<= THISBACK(Port_lcl);
|
|
ip_lcl <<= THISBACK(Ip_lcl);
|
|
hist_text_out.WhenAction = THISBACK(Hist_text_out);
|
|
butt_clr <<= THISBACK(Butt_clr);
|
|
butt_out <<= THISBACK(Butt_out);
|
|
butt_in <<= THISBACK(Butt_in);
|
|
WhenClose = THISBACK(WClose);
|
|
|
|
/* styles */
|
|
lowlight_style = EditField::StyleDefault();
|
|
highlighted_ctrl = NULL;
|
|
|
|
/* members */
|
|
WSADATA wsaData;
|
|
|
|
WSAStartup(MAKEWORD(2,2), &wsaData);
|
|
}
|
|
|
|
void ezcommwin::Ip_rmt()
|
|
{
|
|
/*if ((COMM_TYPE_TCP == comm_type) && !ezcomm.empty())
|
|
{
|
|
std::list<std::pair<std::string, int>*>::iterator pos;
|
|
for (pos = ip_port_rmt.begin(); pos != ip_port_rmt.end(); pos++)
|
|
{
|
|
if ((*pos)->first == ip_rmt.GetData())
|
|
break;
|
|
}
|
|
if (ip_port_rmt.end() == pos)
|
|
{
|
|
disp(ezoi::OILVL_WARN, "select a connected client!");
|
|
ip_rmt.Clear();
|
|
highlight_ctrl(&ip_rmt);
|
|
return;
|
|
}
|
|
}*/
|
|
|
|
lowlight_ctrl(&ip_rmt);
|
|
changes |= CHANGES_RMT;
|
|
}
|
|
|
|
void ezcommwin::Port_rmt()
|
|
{
|
|
/*if ((COMM_TYPE_TCP == comm_type) && !ezcomm.empty())
|
|
{
|
|
std::list<std::pair<std::string, int>*>::iterator pos;
|
|
for (pos = ip_port_rmt.begin(); pos != ip_port_rmt.end(); pos++)
|
|
{
|
|
if ((*pos)->second == port_rmt.GetData())
|
|
break;
|
|
}
|
|
if (ip_port_rmt.end() == pos)
|
|
{
|
|
disp(ezoi::OILVL_WARN, "select a connected client!");
|
|
port_rmt.Clear();
|
|
highlight_ctrl(&port_rmt);
|
|
return;
|
|
}
|
|
}*/
|
|
|
|
lowlight_ctrl(&port_rmt);
|
|
changes |= CHANGES_RMT;
|
|
}
|
|
|
|
void ezcommwin::Port_lcl()
|
|
{
|
|
lowlight_ctrl(&port_lcl);
|
|
changes |= CHANGES_LCL;
|
|
}
|
|
|
|
void ezcommwin::Ip_lcl()
|
|
{
|
|
changes |= CHANGES_LCL;
|
|
}
|
|
|
|
void ezcommwin::Hist_text_out()
|
|
{
|
|
text_out.Set(hist_text_out.GetValue().ToString());
|
|
text_out.SetFocus();
|
|
}
|
|
|
|
void ezcommwin::Hist_text_in()
|
|
{
|
|
mutex_hist.Enter();
|
|
int a= hist_text_in.GetIndex();
|
|
int b=hist_text_in.GetKey(a);
|
|
int c=sock_text_map[b];
|
|
int indx = sock_text_map[static_cast<int>
|
|
(hist_text_in.GetKey(hist_text_in.GetIndex()))];
|
|
|
|
ip_src.SetData(ip_port_rmt.at(indx)->first.c_str());
|
|
port_src.SetData(ip_port_rmt.at(indx)->second);
|
|
text_in.Set(hist_text_in.GetValue(hist_text_in.GetIndex()).ToString());
|
|
mutex_hist.Leave();
|
|
}
|
|
|
|
void ezcommwin::highlight_ctrl(EditField *ctrl)
|
|
{
|
|
lowlight_ctrl(NULL);
|
|
if (ctrl)
|
|
{
|
|
EditField::Style highlight_style = lowlight_style;
|
|
highlight_style.paper = Red();
|
|
ctrl->SetStyle(highlight_style);
|
|
ctrl->SetFocus();
|
|
}
|
|
highlighted_ctrl = ctrl;
|
|
}
|
|
|
|
/*
|
|
parameter: ctrl: NULL: reset highlighted one; non-NULL: reset the control
|
|
if it is highlighted
|
|
*/
|
|
void ezcommwin::lowlight_ctrl(EditField *ctrl)
|
|
{
|
|
if (highlighted_ctrl)
|
|
{
|
|
if (!ctrl || (ctrl == highlighted_ctrl))
|
|
{
|
|
highlighted_ctrl->SetStyle(lowlight_style);
|
|
highlighted_ctrl = NULL;
|
|
if (ctrl)
|
|
Butt_clr();
|
|
}
|
|
}
|
|
}
|
|
|
|
void ezcommwin::disp(ezoi::eoilvl lvl, const char *cnt)
|
|
{
|
|
const char * decorations = "";
|
|
std::string lbl("[7@4A=");
|
|
static time_t previous_time = 0;
|
|
|
|
switch (lvl)
|
|
{
|
|
case ezoi::OILVL_FATAL:
|
|
decorations = "*_";
|
|
break;
|
|
case ezoi::OILVL_WARN:
|
|
decorations = "*d";
|
|
break;
|
|
case ezoi::OILVL_INFO:
|
|
decorations = "";
|
|
break;
|
|
case ezoi::OILVL_NA:
|
|
decorations = "/";
|
|
break;
|
|
}
|
|
lbl.append(decorations);
|
|
if (info.GetData() == cnt)
|
|
lbl.append("o >");
|
|
else
|
|
lbl.append(" ");
|
|
lbl.append(cnt);
|
|
lbl.append("]");
|
|
info.SetData(lbl.c_str());
|
|
info.Info(cnt);
|
|
|
|
/* user-friendly delay */
|
|
time_t current_time = time(NULL);
|
|
const time_t min_time = 1000;
|
|
if (previous_time && current_time
|
|
&& ((current_time - previous_time) < min_time / 1000))
|
|
Sleep(min_time);
|
|
previous_time = time(NULL);
|
|
}
|
|
|
|
bool ezcommwin::create_sockets(std::pair<ezproject::ezcommSocket *,
|
|
ezproject::ezcommSocket *> &sockPair)
|
|
{
|
|
String ip;
|
|
int port;
|
|
sockPair.first = new(ezcommSocket);
|
|
|
|
ip = ip_lcl.GetData();
|
|
if (port_lcl.GetLength())
|
|
port = port_lcl.GetData();
|
|
else
|
|
port = 0;
|
|
try
|
|
{
|
|
sockPair.first->set(ip, port);
|
|
}
|
|
catch (std::string err)
|
|
{
|
|
err.insert(0, "local address: ");
|
|
disp(ezoi::OILVL_FATAL, err.c_str());
|
|
delete sockPair.first;
|
|
sockPair.first = NULL;
|
|
return false;
|
|
}
|
|
|
|
if (!port_rmt.GetLength())
|
|
{
|
|
sockPair.second = NULL;
|
|
return true;
|
|
}
|
|
|
|
sockPair.second = new(ezcommSocket);
|
|
|
|
ip = ip_rmt.GetData();
|
|
port = port_rmt.GetData();
|
|
try
|
|
{
|
|
sockPair.second->set(ip, port);
|
|
}
|
|
catch (std::string err)
|
|
{
|
|
err.insert(0, "remote address: ");
|
|
disp(ezoi::OILVL_FATAL, err.c_str());
|
|
delete sockPair.first;
|
|
sockPair.first = NULL;
|
|
delete sockPair.second;
|
|
sockPair.second = NULL;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
const char *translate_err(int code)
|
|
{
|
|
switch (code)
|
|
{
|
|
case WSANOTINITIALISED:
|
|
return "A successful WSAStartup call must occur before using this function.";
|
|
case WSAENETDOWN:
|
|
return "The network subsystem has failed.";
|
|
case WSAEINPROGRESS:
|
|
return "A blocking Windows Sockets 1.1 call is in progress, or the service provider is still processing a callback function.";
|
|
case WSA_NOT_ENOUGH_MEMORY:
|
|
return "Not enough free memory was available to complete the operation.";
|
|
case WSA_INVALID_HANDLE:
|
|
return "One or more of the values in the lphEvents array is not a valid event object handle.";
|
|
case WSA_INVALID_PARAMETER:
|
|
return "The cEvents parameter does not contain a valid handle count.";
|
|
case WSAEACCES:
|
|
return "The requested address is a broadcast address, but the appropriate flag was not set. Call setsockopt with the SO_BROADCAST parameter to allow the use of the broadcast address.";
|
|
case WSAEINVAL:
|
|
return "An unknown flag was specified, or MSG_OOB was specified for a socket with SO_OOBINLINE enabled.";
|
|
case WSAEINTR:
|
|
return "A blocking Windows Sockets 1.1 call was canceled through WSACancelBlockingCall.";
|
|
case WSAEFAULT:
|
|
return "The buf or to parameters are not part of the user address space, or the tolen parameter is too small.";
|
|
case WSAENETRESET:
|
|
return "The connection has been broken due to keep-alive activity detecting a failure while the operation was in progress.";
|
|
case WSAENOBUFS:
|
|
return "No buffer space is available.";
|
|
case WSAENOTCONN:
|
|
return "The socket is not connected (connection-oriented sockets only.";
|
|
case WSAENOTSOCK:
|
|
return "The descriptor is not a socket.";
|
|
case WSAEOPNOTSUPP:
|
|
return "MSG_OOB was specified, but the socket is not stream-style such as type SOCK_STREAM, OOB data is not supported in the communication domain associated with this socket, or the socket is unidirectional and supports only receive operations.";
|
|
case WSAESHUTDOWN:
|
|
return "The socket has been shut down; it is not possible to sendto on a socket after shutdown has been invoked with how set to SD_SEND or SD_BOTH.";
|
|
case WSAEWOULDBLOCK:
|
|
return "The socket is marked as nonblocking and the requested operation would block.";
|
|
case WSAEMSGSIZE:
|
|
return "The socket is message oriented, and the message is larger than the maximum supported by the underlying transport.";
|
|
case WSAEHOSTUNREACH:
|
|
return "The remote host cannot be reached from this host at this time.";
|
|
case WSAECONNABORTED:
|
|
return "The virtual circuit was terminated due to a time-out or other failure. The application should close the socket as it is no longer usable.";
|
|
case WSAECONNRESET:
|
|
return "The virtual circuit was reset by the remote side executing a hard or abortive close. For UPD sockets, the remote host was unable to deliver a previously sent UDP datagram and responded with a Port Unreachable ICMP packet. The application should close the socket as it is no longer usable.";
|
|
case WSAEADDRNOTAVAIL:
|
|
return "The remote address is not a valid address, for example, ADDR_ANY.";
|
|
case WSAEAFNOSUPPORT:
|
|
return "Addresses in the specified family cannot be used with this socket.";
|
|
case WSAEDESTADDRREQ:
|
|
return "A destination address is required.";
|
|
case WSAENETUNREACH:
|
|
return "The network cannot be reached from this host at this time.";
|
|
case WSAETIMEDOUT:
|
|
return "The connection has been dropped, because of a network failure or because the system on the other end went down without notice.";
|
|
default:
|
|
return "some code unknown...";
|
|
}
|
|
}
|
|
|
|
void ezcommwin::func_client(void *ezcommPi, void *remoteI)
|
|
{
|
|
ezComm *ezcommP = static_cast<ezComm *>(ezcommPi);
|
|
ezcommSocket *remote = static_cast<ezcommSocket *>(remoteI);
|
|
std::string ip = remote->ip();
|
|
int port = remote->port();
|
|
|
|
try
|
|
{
|
|
switch (ezcommP->establish(remote))
|
|
{
|
|
case RTTP_RGHT:
|
|
disp(ezoi::OILVL_INFO, "socket closed");
|
|
break;
|
|
default:
|
|
disp(ezoi::OILVL_FATAL, "error returned when establishing");
|
|
}
|
|
}
|
|
catch (std::string err)
|
|
{
|
|
disp(ezoi::OILVL_FATAL, err.c_str());
|
|
}
|
|
catch (int code)
|
|
{
|
|
disp(ezoi::OILVL_FATAL, translate_err(code));
|
|
}
|
|
|
|
ezcomm.remove(ezcommP);
|
|
delete ezcommP;
|
|
|
|
/* remove peer socket item from list */
|
|
String addr = ip;
|
|
String port_str = ConvertInt().Format(port);
|
|
int index;
|
|
|
|
addr += ':';
|
|
addr += port_str;
|
|
|
|
for (index = 0; index < hist_addr_in.GetCount(); index++)
|
|
if (hist_addr_in.GetValue(index) == addr)
|
|
{
|
|
hist_addr_in.Remove(index);
|
|
const char * const disp_str = "a peer disconnected";
|
|
hist_addr_in.Add(disp_str);
|
|
index = hist_addr_in.FindKey(disp_str);
|
|
hist_addr_in.SetIndex(index);
|
|
hist_addr_in.Refresh();
|
|
hist_addr_in.Remove(index);
|
|
break;
|
|
}
|
|
if (hist_addr_in.GetCount() < 1)
|
|
butt_out.Disable();
|
|
|
|
if (ezcomm.empty())
|
|
{
|
|
buf.clear();
|
|
ip_lcl.Enable();
|
|
port_lcl.Enable();
|
|
butt_out.Enable();
|
|
if (COMM_TYPE_TCP == comm_type)
|
|
{
|
|
ip_rmt.Show();
|
|
port_rmt.Show();
|
|
hist_addr_in.Hide();
|
|
}
|
|
butt_in.SetLabel("listen");
|
|
butt_in.Enable();
|
|
comm_type.Enable();
|
|
disp(ezoi::OILVL_INFO, "ready.");
|
|
}
|
|
}
|
|
|
|
void ezcommwin::func_server(void *ezcommPi)
|
|
{
|
|
ezComm *ezcommP = static_cast<ezComm *>(ezcommPi);
|
|
try
|
|
{
|
|
switch (ezcommP->serve())
|
|
{
|
|
case RTTP_RGHT:
|
|
disp(ezoi::OILVL_INFO, "server closed");
|
|
break;
|
|
default:
|
|
disp(ezoi::OILVL_FATAL, "error returned when establishing");
|
|
}
|
|
}
|
|
catch (std::string err)
|
|
{
|
|
disp(ezoi::OILVL_FATAL, err.c_str());
|
|
}
|
|
catch (int code)
|
|
{
|
|
disp(ezoi::OILVL_FATAL, translate_err(code));
|
|
}
|
|
|
|
ezcomm.remove(ezcommP);
|
|
delete ezcommP;
|
|
|
|
if (ezcomm.empty())
|
|
{
|
|
buf.clear();
|
|
ip_lcl.Enable();
|
|
port_lcl.Enable();
|
|
butt_out.Enable();
|
|
if (COMM_TYPE_TCP == comm_type)
|
|
{
|
|
ip_rmt.Show();
|
|
port_rmt.Show();
|
|
hist_addr_in.Hide();
|
|
}
|
|
butt_in.SetLabel("listen");
|
|
butt_in.Enable();
|
|
comm_type.Enable();
|
|
disp(ezoi::OILVL_INFO, "ready.");
|
|
}
|
|
}
|
|
|
|
void cb_exec(void * holder, enum eaction action, ezComm *ezcommNew,
|
|
std::pair<ezcommSocket *, ezcommSocket *> sockPair, std::string info)
|
|
{
|
|
ezcommwin *ez = static_cast<ezcommwin *>(holder);
|
|
ez->callbacks(action, ezcommNew, sockPair, info);
|
|
}
|
|
|
|
/*
|
|
return value: 0: exhausted
|
|
*/
|
|
ezcommwin::indexes_t ezcommwin::new_key(void)
|
|
{
|
|
/* if (sock_text_map.empty())
|
|
return max_key = 1;*/
|
|
indexes_t key = max_key + 1;
|
|
if (key) //valid
|
|
return max_key = key;
|
|
for (key = 1; key != 0; key++)
|
|
{
|
|
if (sock_text_map.end() == sock_text_map.find(key))
|
|
return key;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
void ezcommwin::delete_key(ezcommwin::indexes_t key)
|
|
{
|
|
if (key == max_key)
|
|
max_key--; //more can be done
|
|
}
|
|
|
|
ezcommwin::indexes_t ezcommwin::add_peer(std::pair<ezcommSocket *,
|
|
ezcommSocket *> &sockPair)
|
|
{
|
|
std::string ip = sockPair.second->ip();
|
|
String addr = ip;
|
|
int port = sockPair.second->port();
|
|
//ConvertInt ci;
|
|
String port_str = ConvertInt().Format(port);
|
|
int peer_index = -1;
|
|
indexes_t key = new_key();
|
|
std::vector<std::pair<std::string, int>*>::iterator it;
|
|
|
|
if (0 == key)
|
|
disp(ezoi::OILVL_WARN, "Too many peers in history!");
|
|
ip_src.SetData(addr);
|
|
addr += ':';
|
|
port_src.SetData(sockPair.second->port());
|
|
addr += port_str;
|
|
switch (comm_type)
|
|
{
|
|
case COMM_TYPE_UDP:
|
|
for (it = ip_port_rmt.begin(); it != ip_port_rmt.end(); it++)
|
|
{
|
|
if (((*it)->first == ip) && ((*it)->second == port))
|
|
break;
|
|
peer_index++;
|
|
}
|
|
if (key)
|
|
sock_text_map.insert(map_t(key, ++peer_index));
|
|
if (ip_port_rmt.end() == it)
|
|
peer_index = -1;
|
|
break;
|
|
case COMM_TYPE_TCP:
|
|
for (; (peer_index + 1) < hist_addr_in.GetCount();)
|
|
{
|
|
if (0 == strcmp(hist_addr_in.GetValue(peer_index
|
|
+ 1).ToString(), addr))
|
|
break;
|
|
peer_index++;
|
|
}
|
|
if ((hist_addr_in.GetCount() == peer_index + 1))
|
|
{ //TCP server must guarantee peer quantity is in boundary
|
|
if (key)
|
|
{
|
|
hist_addr_in.Add(key, addr);
|
|
if (-1 == peer_index)
|
|
hist_addr_in.SetIndex(0);
|
|
sock_text_map.insert(map_t(key,
|
|
static_cast<int>(ip_port_rmt.size())));
|
|
}
|
|
peer_index = -1;
|
|
}
|
|
else
|
|
{
|
|
/* relate new key to old ip_port_rmt's index */
|
|
sock_text_map.insert(map_t(key,
|
|
sock_text_map[static_cast<int>
|
|
(hist_addr_in.GetKey(++peer_index))]));
|
|
hist_addr_in.SetIndex(peer_index);
|
|
}
|
|
break;
|
|
}
|
|
if (peer_index < 0)
|
|
{
|
|
std::pair<std::string, int> *vl
|
|
= new std::pair<std::string, int>(ip, port);
|
|
ip_port_rmt.push_back(vl);
|
|
}
|
|
ip_rmt.Disable();
|
|
addr = ip_rmt.GetData();
|
|
ip_rmt.SetData(String(sockPair.second->ip()));
|
|
ip_rmt.AddHistory(HIST_SOCK_DROP_NUM);
|
|
if (addr.GetLength() > 0)
|
|
ip_rmt.SetData(addr);
|
|
ip_rmt.Enable();
|
|
port_rmt.Disable();
|
|
port = port_rmt.GetData();
|
|
port_rmt.SetData(sockPair.second->port());
|
|
port_rmt.AddHistory(HIST_SOCK_DROP_NUM);
|
|
if (port > 0)
|
|
port_rmt.SetData(port);
|
|
port_rmt.Enable();
|
|
return key;
|
|
}
|
|
|
|
void ezcommwin::callbacks(enum eaction action, ezComm *ezcommNew,
|
|
std::pair<ezcommSocket *, ezcommSocket *> sockPair, std::string info)
|
|
{
|
|
int peer_index = -1, port, loop;
|
|
std::list<std::pair<std::string, int>*>::iterator pos;
|
|
indexes_t key;
|
|
|
|
switch (action)
|
|
{
|
|
case ACTION_SERVE:
|
|
disp(ezoi::OILVL_INFO, "listening...");
|
|
butt_in.Enable();
|
|
break;
|
|
case ACTION_ESTABLISH:
|
|
if (ezcommNew)
|
|
{
|
|
ezcommSocket *sockNew = new ezcommSocket(*(sockPair.second));
|
|
ezcomm.push_back(ezcommNew);
|
|
thread_client.Run(callback2(this, &ezcommwin::func_client,
|
|
dynamic_cast<void *>(ezcommNew),
|
|
static_cast<void *>(sockNew)));
|
|
if (0 == info.length())
|
|
{
|
|
add_peer(sockPair);
|
|
break;
|
|
}
|
|
/*to display incoming message, fall through */
|
|
}
|
|
else
|
|
{
|
|
if (0 == info.length())
|
|
{
|
|
if (!buf.empty())
|
|
{
|
|
disp(ezoi::OILVL_INFO, "bound and trying sending...");
|
|
std::vector<std::string>::iterator pos = buf.begin();
|
|
ezcomm.front()->transmit(*pos);
|
|
buf.erase(pos);
|
|
}
|
|
else
|
|
{
|
|
disp(ezoi::OILVL_INFO, "connected");
|
|
butt_out.Enable();
|
|
butt_in.Enable();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
disp(ezoi::OILVL_WARN, info.c_str());
|
|
butt_in.Enable();
|
|
butt_out.Enable();
|
|
}
|
|
break;
|
|
}
|
|
case ACTION_RECEIVE:
|
|
/* peer record */
|
|
mutex_hist.Enter();
|
|
key = add_peer(sockPair);
|
|
|
|
/* content record */
|
|
text_in.Set(info);
|
|
hist_text_in.Add(key, String(info));
|
|
|
|
disp(ezoi::OILVL_INFO, "sth. received");
|
|
mutex_hist.Leave();
|
|
break;
|
|
case ACTION_TRANSMIT:
|
|
if (0 != info.length())
|
|
disp(ezoi::OILVL_WARN, info.c_str());
|
|
else
|
|
disp(ezoi::OILVL_INFO, "sent as commanded");
|
|
butt_in.Enable();
|
|
butt_out.Enable();
|
|
break;
|
|
case ACTION_DISCONNECT:
|
|
break;
|
|
/* case ACTION_NEGLECT:
|
|
break;*/
|
|
case ACTION_MAX:
|
|
disp(ezoi::OILVL_WARN, "invalid action in callback!");
|
|
break;
|
|
}
|
|
}
|
|
|
|
ezComm *ezcommwin::find_ezcomm(void)
|
|
{
|
|
ezComm *ret = NULL;
|
|
std::list<ezproject::ezComm*>::iterator pos;
|
|
std::pair<std::string, int> *vl;
|
|
|
|
mutex_hist.Enter();
|
|
vl = ip_port_rmt.at(sock_text_map[static_cast<int>
|
|
(hist_addr_in.GetKey(hist_addr_in.GetIndex()))]);
|
|
for (pos = ezcomm.begin(); pos != ezcomm.end(); pos++)
|
|
{
|
|
if (((*pos)->ip() == vl->first)
|
|
&& ((*pos)->port() == vl->second))
|
|
{
|
|
ret = *pos;
|
|
break;
|
|
}
|
|
}
|
|
mutex_hist.Leave();
|
|
return ret;
|
|
}
|
|
|
|
void ezcommwin::Butt_out()
|
|
{
|
|
enum {
|
|
BUTT_OUT_RESULT_FAILURE,
|
|
BUTT_OUT_RESULT_SENT_NEWLY,
|
|
BUTT_OUT_RESULT_SENT_OLD
|
|
} result = BUTT_OUT_RESULT_FAILURE;
|
|
|
|
if (ezcomm.empty())
|
|
{
|
|
if ((0 == ip_rmt.GetLength()) || (0 == port_rmt.GetLength()))
|
|
{
|
|
disp(ezoi::OILVL_FATAL, "Input destination's IP & port!");
|
|
if (0 == ip_rmt.GetLength())
|
|
highlight_ctrl(&ip_rmt);
|
|
else
|
|
highlight_ctrl(&port_rmt);
|
|
}
|
|
else
|
|
{
|
|
std::pair<ezproject::ezcommSocket *,
|
|
ezproject::ezcommSocket *> sockPair;
|
|
|
|
butt_out.Disable();
|
|
butt_in.Disable();
|
|
comm_type.Disable();
|
|
|
|
disp(ezoi::OILVL_INFO, "connecting...");
|
|
if (create_sockets(sockPair))
|
|
{
|
|
ezComm *ezcommNew = NULL;
|
|
|
|
try
|
|
{
|
|
switch (comm_type)
|
|
{
|
|
case COMM_TYPE_UDP:
|
|
ezcommNew = new ezUdp(cb_exec, this,
|
|
sockPair.first);
|
|
break;
|
|
case COMM_TYPE_TCP:
|
|
ezcommNew = new ezTcp(cb_exec, this,
|
|
sockPair.first);
|
|
break;
|
|
}
|
|
if (ezcommNew)
|
|
{
|
|
ezcomm.push_back(ezcommNew);
|
|
if ((COMM_TYPE_UDP == comm_type)
|
|
|| text_out.GetLength())
|
|
buf.insert(buf.begin(), text_out.Get());
|
|
mutex_hist.Enter();
|
|
thread_client.Run(callback2(this,
|
|
&ezcommwin::func_client,
|
|
dynamic_cast<void *>(ezcommNew),
|
|
static_cast<void *>(sockPair.second)));
|
|
|
|
butt_in.SetLabel("stop listening");
|
|
ip_lcl.Disable();
|
|
ip_lcl.AddHistory(HIST_SOCK_DROP_NUM);
|
|
port_lcl.Disable();
|
|
port_lcl.AddHistory(HIST_SOCK_DROP_NUM);
|
|
result = BUTT_OUT_RESULT_SENT_NEWLY;
|
|
}
|
|
}
|
|
catch (std::string err)
|
|
{
|
|
disp(ezoi::OILVL_FATAL, err.c_str());
|
|
delete ezcommNew;
|
|
ezcommNew = NULL;
|
|
}
|
|
if (result != BUTT_OUT_RESULT_FAILURE)
|
|
{
|
|
const char *ip_p = ip_rmt.GetText().ToString();
|
|
int port_conv = port_rmt.GetData();
|
|
/*std::string ip_str = ip_p;*/
|
|
std::pair<std::string, int> *vl
|
|
= new std::pair<std::string, int>(ip_p, port_conv);
|
|
std::vector<std::pair<std::string, int>*>::iterator it;
|
|
|
|
for (it = ip_port_rmt.begin(); it != ip_port_rmt.end();
|
|
it++)
|
|
delete *it;
|
|
ip_port_rmt.clear();
|
|
sock_text_map.clear();
|
|
hist_text_in.Clear();
|
|
text_in.Clear();
|
|
if (COMM_TYPE_TCP == comm_type)
|
|
{
|
|
String addr = ip_p;
|
|
//hist_addr_in.Clear();
|
|
addr += ':';
|
|
addr += port_rmt.GetText().ToString();
|
|
hist_addr_in.Add(static_cast<int>(ip_port_rmt.size()),
|
|
addr);
|
|
hist_addr_in.SetIndex(0);
|
|
ip_rmt.Hide();
|
|
port_rmt.Hide();
|
|
hist_addr_in.Show();
|
|
}
|
|
ip_port_rmt.push_back(vl);
|
|
}
|
|
else
|
|
{
|
|
delete sockPair.first;
|
|
delete sockPair.second;
|
|
comm_type.Enable();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (comm_type)
|
|
{
|
|
case COMM_TYPE_UDP:
|
|
if ((0 == ip_rmt.GetLength()) || (0 == port_rmt.GetLength()))
|
|
{
|
|
disp(ezoi::OILVL_FATAL, "Input destination's IP & port!");
|
|
if (0 == ip_rmt.GetLength())
|
|
highlight_ctrl(&ip_rmt);
|
|
else
|
|
highlight_ctrl(&port_rmt);
|
|
}
|
|
else
|
|
result = BUTT_OUT_RESULT_SENT_OLD;
|
|
break;
|
|
case COMM_TYPE_TCP:
|
|
if (hist_addr_in.GetValue().ToString().IsEmpty())
|
|
//never reaches here
|
|
disp(ezoi::OILVL_FATAL, "Select destination!");
|
|
else
|
|
result = BUTT_OUT_RESULT_SENT_OLD;
|
|
}
|
|
if (result != BUTT_OUT_RESULT_FAILURE)
|
|
{
|
|
result = BUTT_OUT_RESULT_FAILURE;
|
|
disp(ezoi::OILVL_INFO, "sending...");
|
|
if ((COMM_TYPE_UDP == comm_type) && (changes & CHANGES_RMT))
|
|
{
|
|
String ip;
|
|
int port;
|
|
ezcommSocket *remote = NULL;
|
|
|
|
remote = new(ezcommSocket);
|
|
ip = ip_rmt.GetData();
|
|
port = port_rmt.GetData();
|
|
try
|
|
{
|
|
remote->set(ip, port);
|
|
ezcomm.front()->transmit(text_out.Get(), remote);
|
|
result = BUTT_OUT_RESULT_SENT_OLD;
|
|
}
|
|
catch (std::string err)
|
|
{
|
|
disp(ezoi::OILVL_FATAL, err.c_str());
|
|
delete remote;
|
|
remote = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
ezComm *ezp = NULL;
|
|
|
|
switch (comm_type)
|
|
{
|
|
case COMM_TYPE_UDP:
|
|
ezp = ezcomm.front();
|
|
break;
|
|
case COMM_TYPE_TCP:
|
|
ezp = find_ezcomm();
|
|
}
|
|
if (ezp)
|
|
{
|
|
ezp->transmit(text_out.Get());
|
|
result = BUTT_OUT_RESULT_SENT_OLD;
|
|
}
|
|
else
|
|
disp(ezoi::OILVL_FATAL, "No destination detected");
|
|
}
|
|
}
|
|
}
|
|
|
|
changes = 0;
|
|
switch (result)
|
|
{
|
|
case BUTT_OUT_RESULT_SENT_NEWLY:
|
|
case BUTT_OUT_RESULT_SENT_OLD:
|
|
ip_rmt.AddHistory(HIST_SOCK_DROP_NUM);
|
|
port_rmt.AddHistory(HIST_SOCK_DROP_NUM);
|
|
if (text_out.GetLength())
|
|
{
|
|
int text_index;
|
|
|
|
text_index = hist_text_out.Find(text_out.Get());
|
|
if (text_index < 0)
|
|
hist_text_out.Add(text_out.Get());
|
|
else
|
|
hist_text_out.SetIndex(text_index);
|
|
text_out.SetCursor(0);
|
|
}
|
|
if (BUTT_OUT_RESULT_SENT_NEWLY == result)
|
|
mutex_hist.Leave();
|
|
break;
|
|
case BUTT_OUT_RESULT_FAILURE:
|
|
butt_out.Enable();
|
|
butt_in.Enable();
|
|
}
|
|
}
|
|
|
|
void ezcommwin::Butt_in()
|
|
{
|
|
if (!ezcomm.empty())
|
|
{
|
|
butt_in.Disable();
|
|
butt_out.Disable();
|
|
disp(ezoi::OILVL_INFO, "disconnecting...");
|
|
kill_all();
|
|
ip_rmt.Show();
|
|
port_rmt.Show();
|
|
hist_addr_in.Clear();
|
|
hist_addr_in.Hide();
|
|
}
|
|
else
|
|
{
|
|
if (0 == port_lcl.GetLength())
|
|
{
|
|
disp(ezoi::OILVL_FATAL, "Input local port!");
|
|
highlight_ctrl(&port_lcl);
|
|
butt_in.Enable();
|
|
}
|
|
else
|
|
{
|
|
std::pair<ezproject::ezcommSocket *,
|
|
ezproject::ezcommSocket *> sockPair;
|
|
butt_in.Disable();
|
|
if (COMM_TYPE_TCP == comm_type)
|
|
butt_out.Disable();
|
|
comm_type.Disable();
|
|
if (!create_sockets(sockPair))
|
|
{
|
|
butt_in.Enable();
|
|
butt_out.Enable();
|
|
comm_type.Enable();
|
|
}
|
|
else
|
|
{
|
|
ezComm *ezcommNew = NULL;
|
|
|
|
try
|
|
{
|
|
switch (comm_type)
|
|
{
|
|
case COMM_TYPE_UDP:
|
|
ezcommNew = new ezUdp(cb_exec, this,
|
|
sockPair.first);
|
|
break;
|
|
case COMM_TYPE_TCP:
|
|
ezcommNew = new ezTcp(cb_exec, this,
|
|
sockPair.first);
|
|
break;
|
|
}
|
|
if (ezcommNew)
|
|
{
|
|
ezcomm.push_back(ezcommNew);
|
|
thread_server.Run(callback1(this,
|
|
&ezcommwin::func_server,
|
|
dynamic_cast<void *>(ezcommNew)));
|
|
butt_in.SetLabel("stop listening");
|
|
if (COMM_TYPE_TCP == comm_type)
|
|
{
|
|
ip_rmt.Hide();
|
|
port_rmt.Hide();
|
|
hist_addr_in.Show();
|
|
}
|
|
disp(ezoi::OILVL_INFO, "listening");
|
|
}
|
|
}
|
|
catch (std::string err)
|
|
{
|
|
disp(ezoi::OILVL_FATAL, err.c_str());
|
|
delete ezcommNew;
|
|
ezcommNew = NULL;
|
|
}
|
|
if (!ezcommNew)
|
|
{
|
|
delete sockPair.first;
|
|
butt_in.Enable();
|
|
butt_out.Enable();
|
|
comm_type.Enable();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void ezcommwin::Butt_clr()
|
|
{
|
|
disp(ezoi::OILVL_NA, msg.At(rand() % msg.GetCount()));
|
|
}
|
|
|
|
GUI_APP_MAIN
|
|
{
|
|
ezcommwin ezcw;
|
|
|
|
ezcw.Run();
|
|
}
|
|
|