KiCad PCB EDA Suite
eda_dde.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2014 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2014 KiCad Developers, see CHANGELOG.TXT for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
29 #include <eda_dde.h>
30 #include <eda_draw_frame.h>
31 #include <id.h>
32 
33 #include <wx/wx.h>
34 
35 static const wxString HOSTNAME( wxT( "localhost" ) );
36 
37 // buffer for read and write data in socket connections
38 #define IPC_BUF_SIZE 4096
40 
41 
42 /**********************************/
43 /* Routines related to the server */
44 /**********************************/
45 
46 /* Function to initialize a server socket
47  */
48 void EDA_DRAW_FRAME::CreateServer( int service, bool local )
49 {
50  wxIPV4address addr;
51 
52  // Set the port number
53  addr.Service( service );
54 
55  // Listen on localhost only if requested
56  if( local )
57  addr.Hostname( HOSTNAME );
58 
59  delete m_socketServer;
60  m_socketServer = new wxSocketServer( addr );
61 
62  m_socketServer->SetNotify( wxSOCKET_CONNECTION_FLAG );
63  m_socketServer->SetEventHandler( *this, ID_EDA_SOCKET_EVENT_SERV );
64  m_socketServer->Notify( true );
65 }
66 
67 
68 /* Function called on every client request.
69  */
70 void EDA_DRAW_FRAME::OnSockRequest( wxSocketEvent& evt )
71 {
72  size_t len;
73  wxSocketBase* sock = evt.GetSocket();
74 
75  switch( evt.GetSocketEvent() )
76  {
77  case wxSOCKET_INPUT:
78  sock->Read( client_ipc_buffer, 1 );
79 
80  if( sock->LastCount() == 0 )
81  break; // No data, occurs on opening connection
82 
83  sock->Read( client_ipc_buffer + 1, IPC_BUF_SIZE - 2 );
84  len = 1 + sock->LastCount();
85  client_ipc_buffer[len] = 0;
87  break;
88 
89  case wxSOCKET_LOST:
90  return;
91  break;
92 
93  default:
94  wxPrintf( wxT( "EDA_DRAW_FRAME::OnSockRequest() error: Invalid event !" ) );
95  break;
96  }
97 }
98 
99 
100 /* Function called when a connection is requested by a client.
101  */
102 void EDA_DRAW_FRAME::OnSockRequestServer( wxSocketEvent& evt )
103 {
104  wxSocketBase* socket;
105  wxSocketServer* server = (wxSocketServer*) evt.GetSocket();
106 
107  socket = server->Accept();
108 
109  if( socket == NULL )
110  return;
111 
112  m_sockets.push_back( socket );
113 
114  socket->Notify( true );
115  socket->SetEventHandler( *this, ID_EDA_SOCKET_EVENT );
116  socket->SetNotify( wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG );
117 }
118 
119 
120 /**********************************/
121 /* Routines related to the CLIENT */
122 /**********************************/
123 
124 /* Used by a client to sent (by a socket connection) a data to a server.
125  * - Open a Socket Client connection
126  * - Send the buffer cmdline
127  * - Close the socket connection
128  *
129  * service is the service number for the TC/IP connection
130  */
131 bool SendCommand( int service, const char* cmdline )
132 {
133  wxSocketClient* sock_client;
134  bool success = false;
135  wxIPV4address addr;
136 
137  // Create a connexion
138  addr.Hostname( HOSTNAME );
139  addr.Service( service );
140 
141  // Mini-tutorial for Connect() :-)
142  // (JP CHARRAS Note: see wxWidgets: sockets/client.cpp sample)
143  // ---------------------------
144  //
145  // There are two ways to use Connect(): blocking and non-blocking,
146  // depending on the value passed as the 'wait' (2nd) parameter.
147  //
148  // Connect(addr, true) will wait until the connection completes,
149  // returning true on success and false on failure. This call blocks
150  // the GUI (this might be changed in future releases to honor the
151  // wxSOCKET_BLOCK flag).
152  //
153  // Connect(addr, false) will issue a nonblocking connection request
154  // and return immediately. If the return value is true, then the
155  // connection has been already successfully established. If it is
156  // false, you must wait for the request to complete, either with
157  // WaitOnConnect() or by watching wxSOCKET_CONNECTION / LOST
158  // events (please read the documentation).
159  //
160  // WaitOnConnect() itself never blocks the GUI (this might change
161  // in the future to honor the wxSOCKET_BLOCK flag). This call will
162  // return false on timeout, or true if the connection request
163  // completes, which in turn might mean:
164  //
165  // a) That the connection was successfully established
166  // b) That the connection request failed (for example, because
167  // it was refused by the peer.
168  //
169  // Use IsConnected() to distinguish between these two.
170  //
171  // So, in a brief, you should do one of the following things:
172  //
173  // For blocking Connect:
174  //
175  // bool success = client->Connect(addr, true);
176  //
177  // For nonblocking Connect:
178  //
179  // client->Connect(addr, false);
180  //
181  // bool waitmore = true;
182  // while (! client->WaitOnConnect(seconds, millis) && waitmore )
183  // {
184  // // possibly give some feedback to the user,
185  // // update waitmore if needed.
186  // }
187  // bool success = client->IsConnected();
188  //
189  // And that's all :-)
190 
191  sock_client = new wxSocketClient();
192  sock_client->SetTimeout( 2 ); // Time out in Seconds
193  sock_client->Connect( addr, false );
194  sock_client->WaitOnConnect( 0, 100 );
195 
196  if( sock_client->Ok() && sock_client->IsConnected() )
197  {
198  success = true;
199  sock_client->SetFlags( wxSOCKET_NOWAIT /*wxSOCKET_WAITALL*/ );
200  sock_client->Write( cmdline, strlen( cmdline ) );
201  }
202 
203  sock_client->Close();
204  sock_client->Destroy();
205  return success;
206 }
DDE server & client.
#define IPC_BUF_SIZE
Definition: eda_dde.cpp:38
void OnSockRequestServer(wxSocketEvent &evt)
Definition: eda_dde.cpp:102
std::vector< wxSocketBase * > m_sockets
interprocess communication
static char client_ipc_buffer[IPC_BUF_SIZE]
Definition: eda_dde.cpp:39
bool SendCommand(int service, const char *cmdline)
Definition: eda_dde.cpp:131
virtual void ExecuteRemoteCommand(const char *cmdline)
Execute a remote command send via a socket to the application, port KICAD_PCB_PORT_SERVICE_NUMBER (cu...
#define NULL
static const wxString HOSTNAME(wxT("localhost"))
wxSocketServer * m_socketServer
void OnSockRequest(wxSocketEvent &evt)
Definition: eda_dde.cpp:70
void CreateServer(int service, bool local=true)
Definition: eda_dde.cpp:48