1 /* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
3 Copyright (C) 2009 Maxim Ermilov <zaspire@rambler.ru>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/ioctl.h>
23 #include <netinet/in.h>
24 #include <netinet/tcp.h>
30 #include <glib/gi18n.h>
32 #include "debugger-server.h"
34 typedef struct _DebuggerServerPrivate DebuggerServerPrivate
;
35 struct _DebuggerServerPrivate
45 #define DEBUGGER_SERVER_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), DEBUGGER_TYPE_SERVER, DebuggerServerPrivate))
54 #define CANT_SEND _("App exited unexpectedly.")
55 #define CANT_RECV _("App exited unexpectedly.")
58 static guint server_signals
[LAST_SIGNAL
] = { 0 };
60 G_DEFINE_TYPE (DebuggerServer
, debugger_server
, G_TYPE_OBJECT
);
63 debugger_server_init (DebuggerServer
*object
)
65 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
69 priv
->server_socket
= 0;
75 debugger_server_finalize (GObject
*object
)
77 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
85 g_source_remove (priv
->id
);
87 g_list_foreach (priv
->in
, (GFunc
)g_free
, NULL
);
88 g_list_free (priv
->in
);
89 g_list_foreach (priv
->out
, (GFunc
)g_free
, NULL
);
90 g_list_free (priv
->out
);
92 G_OBJECT_CLASS (debugger_server_parent_class
)->finalize (object
);
96 debugger_server_data_arrived (DebuggerServer
*self
)
101 debugger_server_error_signal (DebuggerServer
*self
, const gchar
*text
)
106 debugger_server_class_init (DebuggerServerClass
*klass
)
108 GObjectClass
* object_class
= G_OBJECT_CLASS (klass
);
110 g_type_class_add_private (klass
, sizeof (DebuggerServerPrivate
));
112 object_class
->finalize
= debugger_server_finalize
;
114 klass
->data_arrived
= debugger_server_data_arrived
;
115 klass
->error
= debugger_server_error_signal
;
117 server_signals
[DATA_ARRIVED
] =
118 g_signal_new ("data-arrived",
119 G_OBJECT_CLASS_TYPE (klass
),
121 G_STRUCT_OFFSET (DebuggerServerClass
, data_arrived
),
123 g_cclosure_marshal_VOID__VOID
,
125 server_signals
[ERROR_SIGNAL
] =
126 g_signal_new ("error",
127 G_OBJECT_CLASS_TYPE (klass
),
129 G_STRUCT_OFFSET (DebuggerServerClass
, error
),
131 g_cclosure_marshal_VOID__POINTER
,
132 G_TYPE_NONE
, 1, G_TYPE_POINTER
);
136 SourceFunc (gpointer d
)
138 DebuggerServer
*object
= DEBUGGER_SERVER (d
);
139 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
142 if (priv
->socket
== 0)
145 struct timeval timeo
;
146 struct sockaddr
*cp
= NULL
;
150 FD_SET(priv
->server_socket
, &accept_fd
);
153 if (select(priv
->server_socket
+ 1,&accept_fd
,NULL
,NULL
,&timeo
) > 0)
155 if(FD_ISSET(priv
->server_socket
,&accept_fd
))
157 if ((priv
->socket
= accept(priv
->server_socket
, cp
, &sz
)) == -1)
159 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, "Can not accept.");
162 close (priv
->server_socket
);
169 if (ioctl (priv
->socket
, FIONREAD
, &len
) == -1)
171 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, "Error in ioctl call.");
178 if (recv (priv
->socket
, &len
, 4, 0) == -1)
180 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, CANT_RECV
);
185 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, "Incorrect data recived.");
188 buf
= g_new (char, len
+ 1);
191 if (ioctl (priv
->socket
, FIONREAD
, &in
) == -1)
193 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, "Error in ioctl call.");
199 if (recv (priv
->socket
, buf
, len
, 0) == -1)
201 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, CANT_RECV
);
206 priv
->in
= g_list_append (priv
->in
, buf
);
207 g_signal_emit (object
, server_signals
[DATA_ARRIVED
], 0);
209 while (priv
->out
!= NULL
)
211 size
= strlen ((gchar
*)priv
->out
->data
) + 1;
212 if (send(priv
->socket
, &size
, 4, 0) == -1)
214 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, CANT_SEND
);
217 if (send(priv
->socket
, priv
->out
->data
, size
, 0) == -1)
219 g_signal_emit (object
, server_signals
[ERROR_SIGNAL
], 0, CANT_SEND
);
222 g_free (priv
->out
->data
);
223 priv
->out
= g_list_delete_link (priv
->out
, priv
->out
);
225 g_signal_emit (object
, server_signals
[DATA_ARRIVED
], 0);//TODO:FIX
230 close (priv
->socket
);
238 debugger_server_new (gint port
)
240 DebuggerServer
* object
= g_object_new (DEBUGGER_TYPE_SERVER
, NULL
);
241 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
242 struct sockaddr_in serverAddr
;
245 priv
->server_socket
= socket (AF_INET
, SOCK_STREAM
, 0);
247 if (priv
->server_socket
== -1)
250 serverAddr
.sin_family
= AF_INET
;
251 serverAddr
.sin_addr
.s_addr
= htonl (INADDR_ANY
);
252 serverAddr
.sin_port
= htons (port
);
253 setsockopt (priv
->server_socket
, IPPROTO_TCP
, TCP_NODELAY
, (char *) &flag
, sizeof(int));
254 if (bind (priv
->server_socket
, ((struct sockaddr
*)&serverAddr
), sizeof (serverAddr
)) == -1)
256 g_warning("%s\n", strerror(errno
));
257 g_object_unref (object
);
260 listen (priv
->server_socket
, 5);
262 priv
->id
= g_timeout_add (2, (GSourceFunc
)SourceFunc
, object
);
268 debugger_server_send_line (DebuggerServer
*object
, const gchar
* line
)
270 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
271 g_assert (line
!= NULL
);
272 priv
->out
= g_list_append (priv
->out
, g_strdup (line
));
276 debugger_server_stop (DebuggerServer
*object
)
278 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
284 debugger_server_get_line (DebuggerServer
*object
)
286 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
289 g_assert (priv
->in
!= NULL
);
291 g_assert (priv
->in
->data
!= NULL
);
293 ret
= g_strdup ((gchar
*)priv
->in
->data
);
295 priv
->in
= g_list_delete_link (priv
->in
, priv
->in
);
300 debugger_server_get_line_col (DebuggerServer
*object
)
302 DebuggerServerPrivate
*priv
= DEBUGGER_SERVER_PRIVATE (object
);
303 return g_list_length (priv
->in
);