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