aboutsummaryrefslogtreecommitdiffstats
path: root/echld/echld-util.c
blob: a8b5a1c3d4d5d54e14af7c8a35704fbcbcb3abac (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
/* echld-util.c
 *  utility for echld
 *
 * Wireshark - Network traffic analyzer
 * By Gerald Combs <gerald@wireshark.org>
 * Copyright 1998 Gerald Combs
 *
 * Copyright (c) 2013 by Luis Ontanon <luis@ontanon.org>
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 */

#include "config.h"

#include "echld-int.h"
#include "echld-util.h"

#include <glib.h>

struct _ping {
	struct timeval tv;
	echld_ping_cb_t cb;
	void* cb_data;
};

static long timevaldiff(struct timeval *starttime, struct timeval *finishtime) {
  long msec;
  msec=(finishtime->tv_sec-starttime->tv_sec)*1000;
  msec+=(finishtime->tv_usec-starttime->tv_usec)/1000;
  return msec;
}

static gboolean pong(echld_msg_type_t type, GByteArray* ba _U_, void* data) {
	struct _ping* p = (struct _ping*)data;
	struct timeval t;
	long ret = -1;
	gettimeofday(&t,NULL);


	switch (type) {
		case ECHLD_PONG:
			ret = timevaldiff(&(p->tv),&t);
			break;
		default:
			ret = -1;
			break;
	}

	if (p->cb) p->cb(ret, p->cb_data);

	g_free(p);

	return TRUE;
}


extern echld_state_t echld_ping(int chld_id, echld_ping_cb_t pcb, void* cb_data) {
	struct _ping* p = g_new0(struct _ping,1);

	p->cb = pcb;
	p->cb_data = cb_data;
	gettimeofday(&(p->tv),NULL);

	return echld_reqh(chld_id, ECHLD_PING, 0, NULL, pong, p);
}


struct _get_param {
	const char* name;
	echld_param_cb_t cb;
	void* cb_data;
	echld_bool_t (*dec)(enc_msg_t*, char**, char**);
	echld_bool_t (*dec_err)(enc_msg_t*, int* , char**);
	const char** err_msg;
};

#define CHNULL ((char*)NULL)

static gboolean got_param(echld_msg_type_t type, GByteArray* ba _U_, void* data) {
	struct _get_param* g = (struct _get_param*)data;
	char* err_msg;

	switch (type) {
		case ECHLD_PARAM:
			if (g->cb) {
				char* param;
				char* value;
				g->dec(ba,&param,&value);
				g->cb(param,value,NULL,g->cb_data);

			}
			break;
		case ECHLD_ERROR: {
			int errnum;
			g->dec_err(ba,&errnum,&err_msg);
			g->cb(NULL,NULL,err_msg,g->cb_data);
			break;
		}
		default:
			err_msg = g_strdup_printf("other type='%s'",TY(type));
			g->cb(NULL,NULL,err_msg,g->cb_data);
			g_free(err_msg);
			break;
	}

	g_free(g);
	return TRUE;
}

extern echld_state_t echld_get_param(int chld_id, const char* param, echld_param_cb_t acb, void* cb_data) {
	struct _get_param* g = g_new0(struct _get_param,1);
	echld_parent_encoder_t* enc;
	parent_decoder_t* dec;
	enc_msg_t* em;

	echld_get_all_codecs(NULL, NULL, &enc, &dec);

	em = enc->get_param(param);

	g->name = param;
	g->cb = acb;
	g->cb_data = cb_data;
	g->dec = dec->param;
	g->dec_err = dec->error;

	return echld_reqh(chld_id, ECHLD_GET_PARAM, 0, em, got_param, g);
}

extern echld_state_t echld_set_param(int chld_id, const char* param, const char* value, echld_param_cb_t acb, void* cb_data) {
	struct _get_param* g = g_new0(struct _get_param,1);
	echld_parent_encoder_t* enc;
	parent_decoder_t* dec;
	enc_msg_t* em;

	echld_get_all_codecs(NULL, NULL, &enc, &dec);

	em = enc->set_param(param,value);

	g->name = param;
	g->cb = acb;
	g->cb_data = cb_data;
	g->dec = dec->param;
	g->dec_err = dec->error;

	return echld_reqh(chld_id, ECHLD_SET_PARAM, 0, em, got_param, g);
}

typedef struct _close {
	echld_close_cb_t cb;
	void* cb_data;
} close_t;

static gboolean closed(echld_msg_type_t type, GByteArray* ba, void* data) {
	close_t* c = (close_t*)data;
	parent_decoder_t* dec;
	char* err_msg;

	echld_get_all_codecs(NULL, NULL, NULL, &dec);

	switch (type) {
		case ECHLD_CLOSING: {
			if (c->cb) {
				c->cb(NULL,c->cb_data);
			}
			break;
		}
		case ECHLD_ERROR: {
			int errnum;

			if ( dec->error(ba, &errnum ,&err_msg) ) {
				c->cb(err_msg,c->cb_data);
				g_free(err_msg);
			} else {
				c->cb("Canot decode error message",c->cb_data);
			}
			break;
		}
		default:
			err_msg = g_strdup_printf("other type='%s'",TY(type));
			c->cb(err_msg,c->cb_data);
			g_free(err_msg);
			break;
	}

	g_free(c);
	return TRUE;

}

echld_state_t echld_close(int child_id, echld_close_cb_t pcb, void* cb_data) {
	close_t* c = g_new0(close_t,1);
	c->cb = pcb;
	c->cb_data = cb_data;

	return echld_reqh(child_id,ECHLD_CLOSE_CHILD, 0, NULL, closed, c);
}