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 <fctsys.h>
30 #include <eda_dde.h>
31 #include <draw_frame.h>
32 #include <id.h>
33 #include <common.h>
34 #include <macros.h>
35 
36 static const wxString HOSTNAME( wxT( "localhost" ) );
37 
38 // buffer for read and write data in socket connections
39 #define IPC_BUF_SIZE 4096
41 
42 
43 /**********************************/
44 /* Routines related to the server */
45 /**********************************/
46 
47 /* Function to initialize a server socket
48  */
49 void EDA_DRAW_FRAME::CreateServer( int service, bool local )
50 {
51  wxIPV4address addr;
52 
53  // Set the port number
54  addr.Service( service );
55 
56  // Listen on localhost only if requested
57  if( local )
58  addr.Hostname( HOSTNAME );
59 
60  delete m_socketServer;
61  m_socketServer = new wxSocketServer( addr );
62 
63  m_socketServer->SetNotify( wxSOCKET_CONNECTION_FLAG );
64  m_socketServer->SetEventHandler( *this, ID_EDA_SOCKET_EVENT_SERV );
65  m_socketServer->Notify( true );
66 }
67 
68 
69 /* Function called on every client request.
70  */
71 void EDA_DRAW_FRAME::OnSockRequest( wxSocketEvent& evt )
72 {
73  size_t len;
74  wxSocketBase* sock = evt.GetSocket();
75 
76  switch( evt.GetSocketEvent() )
77  {
78  case wxSOCKET_INPUT:
79  sock->Read( client_ipc_buffer, 1 );
80 
81  if( sock->LastCount() == 0 )
82  break; // No data, occurs on opening connection
83 
84  sock->Read( client_ipc_buffer + 1, IPC_BUF_SIZE - 2 );
85  len = 1 + sock->LastCount();
86  client_ipc_buffer[len] = 0;
87  ExecuteRemoteCommand( client_ipc_buffer );
88  break;
89 
90  case wxSOCKET_LOST:
91  return;
92  break;
93 
94  default:
95  wxPrintf( wxT( "EDA_DRAW_FRAME::OnSockRequest() error: Invalid event !" ) );
96  break;
97  }
98 }
99 
100 
101 /* Function called when a connection is requested by a client.
102  */
103 void EDA_DRAW_FRAME::OnSockRequestServer( wxSocketEvent& evt )
104 {
105  wxSocketBase* socket;
106  wxSocketServer* server = (wxSocketServer*) evt.GetSocket();
107 
108  socket = server->Accept();
109 
110  if( socket == NULL )
111  return;
112 
113  m_sockets.push_back( socket );
114 
115  socket->Notify( true );
116  socket->SetEventHandler( *this, ID_EDA_SOCKET_EVENT );
117  socket->SetNotify( wxSOCKET_INPUT_FLAG | wxSOCKET_LOST_FLAG );
118 }
119 
120 
121 /**********************************/
122 /* Routines related to the CLIENT */
123 /**********************************/
124 
125 /* Used by a client to sent (by a socket connection) a data to a server.
126  * - Open a Socket Client connection
127  * - Send the buffer cmdline
128  * - Close the socket connection
129  *
130  * service is the service number for the TC/IP connection
131  */
132 bool SendCommand( int service, const char* cmdline )
133 {
134  wxSocketClient* sock_client;
135  bool success = false;
136  wxIPV4address addr;
137 
138  // Create a connexion
139  addr.Hostname( HOSTNAME );
140  addr.Service( service );
141 
142  // Mini-tutorial for Connect() :-)
143  // (JP CHARRAS Note: see wxWidgets: sockets/client.cpp sample)
144  // ---------------------------
145  //
146  // There are two ways to use Connect(): blocking and non-blocking,
147  // depending on the value passed as the 'wait' (2nd) parameter.
148  //
149  // Connect(addr, true) will wait until the connection completes,
150  // returning true on success and false on failure. This call blocks
151  // the GUI (this might be changed in future releases to honor the
152  // wxSOCKET_BLOCK flag).
153  //
154  // Connect(addr, false) will issue a nonblocking connection request
155  // and return immediately. If the return value is true, then the
156  // connection has been already successfully established. If it is
157  // false, you must wait for the request to complete, either with
158  // WaitOnConnect() or by watching wxSOCKET_CONNECTION / LOST
159  // events (please read the documentation).
160  //
161  // WaitOnConnect() itself never blocks the GUI (this might change
162  // in the future to honor the wxSOCKET_BLOCK flag). This call will
163  // return false on timeout, or true if the connection request
164  // completes, which in turn might mean:
165  //
166  // a) That the connection was successfully established
167  // b) That the connection request failed (for example, because
168  // it was refused by the peer.
169  //
170  // Use IsConnected() to distinguish between these two.
171  //
172  // So, in a brief, you should do one of the following things:
173  //
174  // For blocking Connect:
175  //
176  // bool success = client->Connect(addr, true);
177  //
178  // For nonblocking Connect:
179  //
180  // client->Connect(addr, false);
181  //
182  // bool waitmore = true;
183  // while (! client->WaitOnConnect(seconds, millis) && waitmore )
184  // {
185  // // possibly give some feedback to the user,
186  // // update waitmore if needed.
187  // }
188  // bool success = client->IsConnected();
189  //
190  // And that's all :-)
191 
192  sock_client = new wxSocketClient();
193  sock_client->SetTimeout( 2 ); // Time out in Seconds
194  sock_client->Connect( addr, false );
195  sock_client->WaitOnConnect( 0, 100 );
196 
197  if( sock_client->Ok() && sock_client->IsConnected() )
198  {
199  success = true;
200  sock_client->SetFlags( wxSOCKET_NOWAIT /*wxSOCKET_WAITALL*/ );
201  sock_client->Write( cmdline, strlen( cmdline ) );
202  }
203 
204  sock_client->Close();
205  sock_client->Destroy();
206  return success;
207 }
DDE server & client.
#define IPC_BUF_SIZE
Definition: eda_dde.cpp:39
void OnSockRequestServer(wxSocketEvent &evt)
Definition: eda_dde.cpp:103
std::vector< wxSocketBase * > m_sockets
interprocess communication
Definition: draw_frame.h:77
static char client_ipc_buffer[IPC_BUF_SIZE]
Definition: eda_dde.cpp:40
bool SendCommand(int service, const char *cmdline)
Definition: eda_dde.cpp:132
This file contains miscellaneous commonly used macros and functions.
virtual void ExecuteRemoteCommand(const char *cmdline)
Execute a remote command send via a socket to the application, port KICAD_PCB_PORT_SERVICE_NUMBER (cu...
Definition: draw_frame.h:372
static const wxString HOSTNAME(wxT("localhost"))
wxSocketServer * m_socketServer
Definition: draw_frame.h:76
void OnSockRequest(wxSocketEvent &evt)
Definition: eda_dde.cpp:71
The common library.
void CreateServer(int service, bool local=true)
Definition: eda_dde.cpp:49