The Assimilation Project
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
netgsource.c
Go to the documentation of this file.
1 
29 #include <projectcommon.h>
30 #include <memory.h>
31 #include <glib.h>
32 #include <frameset.h>
33 #include <netgsource.h>
34 
36 
44 
45 FSTATIC gboolean _netgsource_prepare(GSource* source, gint* timeout);
46 FSTATIC gboolean _netgsource_check(GSource* source);
47 FSTATIC gboolean _netgsource_dispatch(GSource* source, GSourceFunc callback, gpointer user_data);
48 FSTATIC void _netgsource_finalize(GSource* source);
50 FSTATIC void _netgsource_del_listener(gpointer);
53 
54 static GSourceFuncs _netgsource_gsourcefuncs = {
59  NULL,
60  NULL
61 };
62 FSTATIC void
64 {
65  Listener* lobj;
66  if (lptr) {
67  lobj = CASTTOCLASS(Listener, lptr);
68  UNREF(lobj);
69  }
70 }
71 
75  GDestroyNotify notify,
76  gint priority,
77  gboolean can_recurse,
79  GMainContext* context,
80  gsize objsize,
81  gpointer userdata
82  )
83 {
84  GSource* gsret;
85  NetGSource* ret;
86  GSourceFuncs* gsf;
87 
89  if (objsize < sizeof(NetGSource)) {
90  objsize = sizeof(NetGSource);
91  }
92  gsf = MALLOCBASECLASS(GSourceFuncs);
93  *gsf = _netgsource_gsourcefuncs;
94 
95  gsret = g_source_new(gsf, objsize);
96  if (gsret == NULL) {
97  FREECLASSOBJ(gsf);
98  g_return_val_if_reached(NULL);
99  }
100  proj_class_register_object(gsret, "GSource");
101  proj_class_register_subclassed(gsret, "NetGSource");
102  ret = CASTTOCLASS(NetGSource, gsret);
103 
104  ret->_gsfuncs = gsf;
105  ret->_userdata = userdata;
106  ret->_netio = iosrc;
107  iosrc->setblockio(iosrc, FALSE);
108  ret->_socket = iosrc->getfd(iosrc);
109  ret->_finalize = notify;
110  ret->_gfd.fd = ret->_socket;
111  ret->_gfd.events = G_IO_IN|G_IO_ERR|G_IO_HUP;
112  ret->_gfd.revents = 0;
116 
117  g_source_add_poll(gsret, &ret->_gfd);
118  g_source_set_priority(gsret, priority);
119  g_source_set_can_recurse(gsret, can_recurse);
120 
121  ret->_gsourceid = g_source_attach(gsret, context);
122 
123  if (ret->_gsourceid == 0) {
124  FREECLASSOBJ(gsf);
125  g_source_remove_poll(gsret, &ret->_gfd);
126  memset(ret, 0, sizeof(*ret));
127  g_source_unref(gsret);
128  gsret = NULL;
129  ret = NULL;
130  g_return_val_if_reached(NULL);
131  }
132  // REF(ret->_netio);
133  ret->_dispatchers = g_hash_table_new_full(NULL, NULL, NULL, _netgsource_del_listener);
134  return ret;
135 }
136 
139 FSTATIC gboolean
140 _netgsource_prepare(GSource* source,
141  gint* timeout)
142 {
143  (void)source; (void)timeout;
144  return _netgsource_check(source);
145 }
146 
150 FSTATIC gboolean
151 _netgsource_check(GSource* gself)
152 {
153  NetGSource* self = CASTTOCLASS(NetGSource, gself);
154  // revents: received events...
155  // @todo: probably should check for errors in revents
156  return ((0 != self->_gfd.revents) || self->_netio->input_queued(self->_netio));
157 }
163 FSTATIC gboolean
164 _netgsource_dispatch(GSource* gself,
165  GSourceFunc ignore_callback,
166  gpointer ignore_userdata)
167 {
168  NetGSource* self = CASTTOCLASS(NetGSource, gself);
169  GSList* gsl;
170  NetAddr* srcaddr;
171  (void)ignore_callback; (void)ignore_userdata;
172  if ((self->_gfd.revents & (G_IO_IN|G_IO_ERR|G_IO_HUP|G_IO_NVAL|G_IO_PRI)) == 0) {
173  DEBUGMSG("%s.%d: Dispatched due to UNKNOWN REASON: 0x%04x"
174  , __FUNCTION__, __LINE__, self->_gfd.revents);
175  }
176  while(NULL != (gsl = self->_netio->recvframesets(self->_netio, &srcaddr))) {
177  for (; NULL != gsl; gsl = gsl->next) {
178  Listener* disp = NULL;
179  FrameSet* fs = CASTTOCLASS(FrameSet, gsl->data);
180  disp = g_hash_table_lookup(self->_dispatchers, GUINT_TO_POINTER((size_t)fs->fstype));
181  if (NULL == disp) {
182  disp = CASTTOCLASS(Listener, g_hash_table_lookup(self->_dispatchers, NULL));
183  }
184  if (NULL != disp) {
185  disp->got_frameset(disp, fs, srcaddr);
186  }else{
187  g_warning("No dispatcher for FrameSet type %d", fs->fstype);
188  }
189  }
190  UNREF(srcaddr);
191  }
192  return TRUE;
193 }
194 
196 FSTATIC void
197 _netgsource_finalize(GSource* gself)
198 {
199 #ifndef __FUNCTION__
200 # define __FUNCTION__ "_netgsource_finalize"
201 #endif
202  NetGSource* self = CASTTOCLASS(NetGSource, gself);
203  DEBUGMSG("%s(%p) FINALIZING!", __FUNCTION__, self);
204  if (self->_finalize) {
205  DEBUGMSG("%s: finalizing object at %p with %p", __FUNCTION__, self->_userdata
206  , self->_finalize);
207  self->_finalize(self->_userdata);
208  }else{
209  if (self->_userdata) {
212  FREECLASSOBJ(self->_userdata);
213  self->_userdata = NULL;
214  DEBUGMSG("%s: FREECLASSOBJ(%p)", __FUNCTION__, self->_userdata);
215  }
216  }
217  if (self->_gsfuncs) {
218  FREECLASSOBJ(self->_gsfuncs);
219  self->_gsfuncs = NULL;
220  }
221  // UNREF(self->_netio);
222  g_hash_table_unref(self->_dispatchers);
223  proj_class_dissociate(gself);// Avoid dangling reference in class system
224 }
226 FSTATIC void
228  const NetAddr* addr,
229  FrameSet* fs)
230 {
231  NetIO* nio = self->_netio;
232  nio->sendaframeset(nio, addr, fs);
233 }
235 FSTATIC void
237  const NetAddr* addr,
238  GSList* fslist)
239 {
240  NetIO* nio = self->_netio;
241  nio->sendframesets(nio, addr, fslist);
242 }
243 FSTATIC void
245  guint16 fstype,
246  Listener* disp)
247 {
248  if (disp) {
249  REF(disp);
250  }
251  g_hash_table_replace(self->_dispatchers, GUINT_TO_POINTER((size_t)fstype), disp);
252 }