• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <string.h>
21 #include <errno.h>
22 
23 #include "sysdeps.h"
24 
25 #define   TRACE_TAG  TRACE_TRANSPORT
26 #include "adb.h"
27 
28 static void transport_unref(atransport *t);
29 
30 static atransport transport_list = {
31     .next = &transport_list,
32     .prev = &transport_list,
33 };
34 
35 ADB_MUTEX_DEFINE( transport_lock );
36 
37 #if ADB_TRACE
38 #define MAX_DUMP_HEX_LEN 16
dump_hex(const unsigned char * ptr,size_t len)39 static void  dump_hex( const unsigned char*  ptr, size_t  len )
40 {
41     int  nn, len2 = len;
42     // Build a string instead of logging each character.
43     // MAX chars in 2 digit hex, one space, MAX chars, one '\0'.
44     char buffer[MAX_DUMP_HEX_LEN *2 + 1 + MAX_DUMP_HEX_LEN + 1 ], *pb = buffer;
45 
46     if (len2 > MAX_DUMP_HEX_LEN) len2 = MAX_DUMP_HEX_LEN;
47 
48     for (nn = 0; nn < len2; nn++) {
49         sprintf(pb, "%02x", ptr[nn]);
50         pb += 2;
51     }
52     sprintf(pb++, " ");
53 
54     for (nn = 0; nn < len2; nn++) {
55         int  c = ptr[nn];
56         if (c < 32 || c > 127)
57             c = '.';
58         *pb++ =  c;
59     }
60     *pb++ = '\0';
61     DR("%s\n", buffer);
62 }
63 #endif
64 
65 void
kick_transport(atransport * t)66 kick_transport(atransport*  t)
67 {
68     if (t && !t->kicked)
69     {
70         int  kicked;
71 
72         adb_mutex_lock(&transport_lock);
73         kicked = t->kicked;
74         if (!kicked)
75             t->kicked = 1;
76         adb_mutex_unlock(&transport_lock);
77 
78         if (!kicked)
79             t->kick(t);
80     }
81 }
82 
83 void
run_transport_disconnects(atransport * t)84 run_transport_disconnects(atransport*  t)
85 {
86     adisconnect*  dis = t->disconnects.next;
87 
88     D("%s: run_transport_disconnects\n", t->serial);
89     while (dis != &t->disconnects) {
90         adisconnect*  next = dis->next;
91         dis->func( dis->opaque, t );
92         dis = next;
93     }
94 }
95 
96 #if ADB_TRACE
97 static void
dump_packet(const char * name,const char * func,apacket * p)98 dump_packet(const char* name, const char* func, apacket* p)
99 {
100     unsigned  command = p->msg.command;
101     int       len     = p->msg.data_length;
102     char      cmd[9];
103     char      arg0[12], arg1[12];
104     int       n;
105 
106     for (n = 0; n < 4; n++) {
107         int  b = (command >> (n*8)) & 255;
108         if (b < 32 || b >= 127)
109             break;
110         cmd[n] = (char)b;
111     }
112     if (n == 4) {
113         cmd[4] = 0;
114     } else {
115         /* There is some non-ASCII name in the command, so dump
116             * the hexadecimal value instead */
117         snprintf(cmd, sizeof cmd, "%08x", command);
118     }
119 
120     if (p->msg.arg0 < 256U)
121         snprintf(arg0, sizeof arg0, "%d", p->msg.arg0);
122     else
123         snprintf(arg0, sizeof arg0, "0x%x", p->msg.arg0);
124 
125     if (p->msg.arg1 < 256U)
126         snprintf(arg1, sizeof arg1, "%d", p->msg.arg1);
127     else
128         snprintf(arg1, sizeof arg1, "0x%x", p->msg.arg1);
129 
130     D("%s: %s: [%s] arg0=%s arg1=%s (len=%d) ",
131         name, func, cmd, arg0, arg1, len);
132     dump_hex(p->data, len);
133 }
134 #endif /* ADB_TRACE */
135 
136 static int
read_packet(int fd,const char * name,apacket ** ppacket)137 read_packet(int  fd, const char* name, apacket** ppacket)
138 {
139     char *p = (char*)ppacket;  /* really read a packet address */
140     int   r;
141     int   len = sizeof(*ppacket);
142     char  buff[8];
143     if (!name) {
144         snprintf(buff, sizeof buff, "fd=%d", fd);
145         name = buff;
146     }
147     while(len > 0) {
148         r = adb_read(fd, p, len);
149         if(r > 0) {
150             len -= r;
151             p   += r;
152         } else {
153             D("%s: read_packet (fd=%d), error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
154             if((r < 0) && (errno == EINTR)) continue;
155             return -1;
156         }
157     }
158 
159 #if ADB_TRACE
160     if (ADB_TRACING) {
161         dump_packet(name, "from remote", *ppacket);
162     }
163 #endif
164     return 0;
165 }
166 
167 static int
write_packet(int fd,const char * name,apacket ** ppacket)168 write_packet(int  fd, const char* name, apacket** ppacket)
169 {
170     char *p = (char*) ppacket;  /* we really write the packet address */
171     int r, len = sizeof(ppacket);
172     char buff[8];
173     if (!name) {
174         snprintf(buff, sizeof buff, "fd=%d", fd);
175         name = buff;
176     }
177 
178 #if ADB_TRACE
179     if (ADB_TRACING) {
180         dump_packet(name, "to remote", *ppacket);
181     }
182 #endif
183     len = sizeof(ppacket);
184     while(len > 0) {
185         r = adb_write(fd, p, len);
186         if(r > 0) {
187             len -= r;
188             p += r;
189         } else {
190             D("%s: write_packet (fd=%d) error ret=%d errno=%d: %s\n", name, fd, r, errno, strerror(errno));
191             if((r < 0) && (errno == EINTR)) continue;
192             return -1;
193         }
194     }
195     return 0;
196 }
197 
transport_socket_events(int fd,unsigned events,void * _t)198 static void transport_socket_events(int fd, unsigned events, void *_t)
199 {
200     atransport *t = _t;
201     D("transport_socket_events(fd=%d, events=%04x,...)\n", fd, events);
202     if(events & FDE_READ){
203         apacket *p = 0;
204         if(read_packet(fd, t->serial, &p)){
205             D("%s: failed to read packet from transport socket on fd %d\n", t->serial, fd);
206         } else {
207             handle_packet(p, (atransport *) _t);
208         }
209     }
210 }
211 
send_packet(apacket * p,atransport * t)212 void send_packet(apacket *p, atransport *t)
213 {
214     unsigned char *x;
215     unsigned sum;
216     unsigned count;
217 
218     p->msg.magic = p->msg.command ^ 0xffffffff;
219 
220     count = p->msg.data_length;
221     x = (unsigned char *) p->data;
222     sum = 0;
223     while(count-- > 0){
224         sum += *x++;
225     }
226     p->msg.data_check = sum;
227 
228     print_packet("send", p);
229 
230     if (t == NULL) {
231         D("Transport is null \n");
232         // Zap errno because print_packet() and other stuff have errno effect.
233         errno = 0;
234         fatal_errno("Transport is null");
235     }
236 
237     if(write_packet(t->transport_socket, t->serial, &p)){
238         fatal_errno("cannot enqueue packet on transport socket");
239     }
240 }
241 
242 /* The transport is opened by transport_register_func before
243 ** the input and output threads are started.
244 **
245 ** The output thread issues a SYNC(1, token) message to let
246 ** the input thread know to start things up.  In the event
247 ** of transport IO failure, the output thread will post a
248 ** SYNC(0,0) message to ensure shutdown.
249 **
250 ** The transport will not actually be closed until both
251 ** threads exit, but the input thread will kick the transport
252 ** on its way out to disconnect the underlying device.
253 */
254 
output_thread(void * _t)255 static void *output_thread(void *_t)
256 {
257     atransport *t = _t;
258     apacket *p;
259 
260     D("%s: starting transport output thread on fd %d, SYNC online (%d)\n",
261        t->serial, t->fd, t->sync_token + 1);
262     p = get_apacket();
263     p->msg.command = A_SYNC;
264     p->msg.arg0 = 1;
265     p->msg.arg1 = ++(t->sync_token);
266     p->msg.magic = A_SYNC ^ 0xffffffff;
267     if(write_packet(t->fd, t->serial, &p)) {
268         put_apacket(p);
269         D("%s: failed to write SYNC packet\n", t->serial);
270         goto oops;
271     }
272 
273     D("%s: data pump started\n", t->serial);
274     for(;;) {
275         p = get_apacket();
276 
277         if(t->read_from_remote(p, t) == 0){
278             D("%s: received remote packet, sending to transport\n",
279               t->serial);
280             if(write_packet(t->fd, t->serial, &p)){
281                 put_apacket(p);
282                 D("%s: failed to write apacket to transport\n", t->serial);
283                 goto oops;
284             }
285         } else {
286             D("%s: remote read failed for transport\n", t->serial);
287             put_apacket(p);
288             break;
289         }
290     }
291 
292     D("%s: SYNC offline for transport\n", t->serial);
293     p = get_apacket();
294     p->msg.command = A_SYNC;
295     p->msg.arg0 = 0;
296     p->msg.arg1 = 0;
297     p->msg.magic = A_SYNC ^ 0xffffffff;
298     if(write_packet(t->fd, t->serial, &p)) {
299         put_apacket(p);
300         D("%s: failed to write SYNC apacket to transport", t->serial);
301     }
302 
303 oops:
304     D("%s: transport output thread is exiting\n", t->serial);
305     kick_transport(t);
306     transport_unref(t);
307     return 0;
308 }
309 
input_thread(void * _t)310 static void *input_thread(void *_t)
311 {
312     atransport *t = _t;
313     apacket *p;
314     int active = 0;
315 
316     D("%s: starting transport input thread, reading from fd %d\n",
317        t->serial, t->fd);
318 
319     for(;;){
320         if(read_packet(t->fd, t->serial, &p)) {
321             D("%s: failed to read apacket from transport on fd %d\n",
322                t->serial, t->fd );
323             break;
324         }
325         if(p->msg.command == A_SYNC){
326             if(p->msg.arg0 == 0) {
327                 D("%s: transport SYNC offline\n", t->serial);
328                 put_apacket(p);
329                 break;
330             } else {
331                 if(p->msg.arg1 == t->sync_token) {
332                     D("%s: transport SYNC online\n", t->serial);
333                     active = 1;
334                 } else {
335                     D("%s: transport ignoring SYNC %d != %d\n",
336                       t->serial, p->msg.arg1, t->sync_token);
337                 }
338             }
339         } else {
340             if(active) {
341                 D("%s: transport got packet, sending to remote\n", t->serial);
342                 t->write_to_remote(p, t);
343             } else {
344                 D("%s: transport ignoring packet while offline\n", t->serial);
345             }
346         }
347 
348         put_apacket(p);
349     }
350 
351     // this is necessary to avoid a race condition that occured when a transport closes
352     // while a client socket is still active.
353     close_all_sockets(t);
354 
355     D("%s: transport input thread is exiting, fd %d\n", t->serial, t->fd);
356     kick_transport(t);
357     transport_unref(t);
358     return 0;
359 }
360 
361 
362 static int transport_registration_send = -1;
363 static int transport_registration_recv = -1;
364 static fdevent transport_registration_fde;
365 
update_transports(void)366 void  update_transports(void)
367 {
368     // nothing to do on the device side
369 }
370 
371 typedef struct tmsg tmsg;
372 struct tmsg
373 {
374     atransport *transport;
375     int         action;
376 };
377 
378 static int
transport_read_action(int fd,struct tmsg * m)379 transport_read_action(int  fd, struct tmsg*  m)
380 {
381     char *p   = (char*)m;
382     int   len = sizeof(*m);
383     int   r;
384 
385     while(len > 0) {
386         r = adb_read(fd, p, len);
387         if(r > 0) {
388             len -= r;
389             p   += r;
390         } else {
391             if((r < 0) && (errno == EINTR)) continue;
392             D("transport_read_action: on fd %d, error %d: %s\n",
393               fd, errno, strerror(errno));
394             return -1;
395         }
396     }
397     return 0;
398 }
399 
400 static int
transport_write_action(int fd,struct tmsg * m)401 transport_write_action(int  fd, struct tmsg*  m)
402 {
403     char *p   = (char*)m;
404     int   len = sizeof(*m);
405     int   r;
406 
407     while(len > 0) {
408         r = adb_write(fd, p, len);
409         if(r > 0) {
410             len -= r;
411             p   += r;
412         } else {
413             if((r < 0) && (errno == EINTR)) continue;
414             D("transport_write_action: on fd %d, error %d: %s\n",
415               fd, errno, strerror(errno));
416             return -1;
417         }
418     }
419     return 0;
420 }
421 
transport_registration_func(int _fd,unsigned ev,void * data)422 static void transport_registration_func(int _fd, unsigned ev, void *data)
423 {
424     tmsg m;
425     adb_thread_t output_thread_ptr;
426     adb_thread_t input_thread_ptr;
427     int s[2];
428     atransport *t;
429 
430     if(!(ev & FDE_READ)) {
431         return;
432     }
433 
434     if(transport_read_action(_fd, &m)) {
435         fatal_errno("cannot read transport registration socket");
436     }
437 
438     t = m.transport;
439 
440     if(m.action == 0){
441         D("transport: %s removing and free'ing %d\n", t->serial, t->transport_socket);
442 
443             /* IMPORTANT: the remove closes one half of the
444             ** socket pair.  The close closes the other half.
445             */
446         fdevent_remove(&(t->transport_fde));
447         adb_close(t->fd);
448 
449         adb_mutex_lock(&transport_lock);
450         t->next->prev = t->prev;
451         t->prev->next = t->next;
452         adb_mutex_unlock(&transport_lock);
453 
454         run_transport_disconnects(t);
455 
456         if (t->product)
457             free(t->product);
458         if (t->serial)
459             free(t->serial);
460 
461         memset(t,0xee,sizeof(atransport));
462         free(t);
463 
464         update_transports();
465         return;
466     }
467 
468     /* don't create transport threads for inaccessible devices */
469     if (t->connection_state != CS_NOPERM) {
470         /* initial references are the two threads */
471         t->ref_count = 2;
472 
473         if(adb_socketpair(s)) {
474             fatal_errno("cannot open transport socketpair");
475         }
476 
477         D("transport: %s (%d,%d) starting\n", t->serial, s[0], s[1]);
478 
479         t->transport_socket = s[0];
480         t->fd = s[1];
481 
482         fdevent_install(&(t->transport_fde),
483                         t->transport_socket,
484                         transport_socket_events,
485                         t);
486 
487         fdevent_set(&(t->transport_fde), FDE_READ);
488 
489         if(adb_thread_create(&input_thread_ptr, input_thread, t)){
490             fatal_errno("cannot create input thread");
491         }
492 
493         if(adb_thread_create(&output_thread_ptr, output_thread, t)){
494             fatal_errno("cannot create output thread");
495         }
496     }
497 
498         /* put us on the master device list */
499     adb_mutex_lock(&transport_lock);
500     t->next = &transport_list;
501     t->prev = transport_list.prev;
502     t->next->prev = t;
503     t->prev->next = t;
504     adb_mutex_unlock(&transport_lock);
505 
506     t->disconnects.next = t->disconnects.prev = &t->disconnects;
507 
508     update_transports();
509 }
510 
init_transport_registration(void)511 void init_transport_registration(void)
512 {
513     int s[2];
514 
515     if(adb_socketpair(s)){
516         fatal_errno("cannot open transport registration socketpair");
517     }
518 
519     transport_registration_send = s[0];
520     transport_registration_recv = s[1];
521 
522     fdevent_install(&transport_registration_fde,
523                     transport_registration_recv,
524                     transport_registration_func,
525                     0);
526 
527     fdevent_set(&transport_registration_fde, FDE_READ);
528 }
529 
530 /* the fdevent select pump is single threaded */
register_transport(atransport * transport)531 static void register_transport(atransport *transport)
532 {
533     tmsg m;
534     m.transport = transport;
535     m.action = 1;
536     D("transport: %s registered\n", transport->serial);
537     if(transport_write_action(transport_registration_send, &m)) {
538         fatal_errno("cannot write transport registration socket\n");
539     }
540 }
541 
remove_transport(atransport * transport)542 static void remove_transport(atransport *transport)
543 {
544     tmsg m;
545     m.transport = transport;
546     m.action = 0;
547     D("transport: %s removed\n", transport->serial);
548     if(transport_write_action(transport_registration_send, &m)) {
549         fatal_errno("cannot write transport registration socket\n");
550     }
551 }
552 
553 
transport_unref_locked(atransport * t)554 static void transport_unref_locked(atransport *t)
555 {
556     t->ref_count--;
557     if (t->ref_count == 0) {
558         D("transport: %s unref (kicking and closing)\n", t->serial);
559         if (!t->kicked) {
560             t->kicked = 1;
561             t->kick(t);
562         }
563         t->close(t);
564         remove_transport(t);
565     } else {
566         D("transport: %s unref (count=%d)\n", t->serial, t->ref_count);
567     }
568 }
569 
transport_unref(atransport * t)570 static void transport_unref(atransport *t)
571 {
572     if (t) {
573         adb_mutex_lock(&transport_lock);
574         transport_unref_locked(t);
575         adb_mutex_unlock(&transport_lock);
576     }
577 }
578 
add_transport_disconnect(atransport * t,adisconnect * dis)579 void add_transport_disconnect(atransport*  t, adisconnect*  dis)
580 {
581     adb_mutex_lock(&transport_lock);
582     dis->next       = &t->disconnects;
583     dis->prev       = dis->next->prev;
584     dis->prev->next = dis;
585     dis->next->prev = dis;
586     adb_mutex_unlock(&transport_lock);
587 }
588 
remove_transport_disconnect(atransport * t,adisconnect * dis)589 void remove_transport_disconnect(atransport*  t, adisconnect*  dis)
590 {
591     dis->prev->next = dis->next;
592     dis->next->prev = dis->prev;
593     dis->next = dis->prev = dis;
594 }
595 
596 
acquire_one_transport(int state,transport_type ttype,const char * serial,char ** error_out)597 atransport *acquire_one_transport(int state, transport_type ttype, const char* serial, char** error_out)
598 {
599     atransport *t;
600     atransport *result = NULL;
601     int ambiguous = 0;
602 
603 retry:
604     if (error_out)
605         *error_out = "device not found";
606 
607     adb_mutex_lock(&transport_lock);
608     for (t = transport_list.next; t != &transport_list; t = t->next) {
609         if (t->connection_state == CS_NOPERM) {
610         if (error_out)
611             *error_out = "insufficient permissions for device";
612             continue;
613         }
614 
615         /* check for matching serial number */
616         if (serial) {
617             if (t->serial && !strcmp(serial, t->serial)) {
618                 result = t;
619                 break;
620             }
621         } else {
622             if (ttype == kTransportUsb && t->type == kTransportUsb) {
623                 if (result) {
624                     if (error_out)
625                         *error_out = "more than one device";
626                     ambiguous = 1;
627                     result = NULL;
628                     break;
629                 }
630                 result = t;
631             } else if (ttype == kTransportLocal && t->type == kTransportLocal) {
632                 if (result) {
633                     if (error_out)
634                         *error_out = "more than one emulator";
635                     ambiguous = 1;
636                     result = NULL;
637                     break;
638                 }
639                 result = t;
640             } else if (ttype == kTransportAny) {
641                 if (result) {
642                     if (error_out)
643                         *error_out = "more than one device and emulator";
644                     ambiguous = 1;
645                     result = NULL;
646                     break;
647                 }
648                 result = t;
649             }
650         }
651     }
652     adb_mutex_unlock(&transport_lock);
653 
654     if (result) {
655          /* offline devices are ignored -- they are either being born or dying */
656         if (result && result->connection_state == CS_OFFLINE) {
657             if (error_out)
658                 *error_out = "device offline";
659             result = NULL;
660         }
661          /* check for required connection state */
662         if (result && state != CS_ANY && result->connection_state != state) {
663             if (error_out)
664                 *error_out = "invalid device state";
665             result = NULL;
666         }
667     }
668 
669     if (result) {
670         /* found one that we can take */
671         if (error_out)
672             *error_out = NULL;
673     } else if (state != CS_ANY && (serial || !ambiguous)) {
674         adb_sleep_ms(1000);
675         goto retry;
676     }
677 
678     return result;
679 }
680 
register_socket_transport(int s,const char * serial,int port,int local)681 void register_socket_transport(int s, const char *serial, int port, int local)
682 {
683     atransport *t = calloc(1, sizeof(atransport));
684     char buff[32];
685 
686     if (!serial) {
687         snprintf(buff, sizeof buff, "T-%p", t);
688         serial = buff;
689     }
690     D("transport: %s init'ing for socket %d, on port %d\n", serial, s, port);
691     if ( init_socket_transport(t, s, port, local) < 0 ) {
692         adb_close(s);
693         free(t);
694         return;
695     }
696     if(serial) {
697         t->serial = strdup(serial);
698     }
699     register_transport(t);
700 }
701 
register_usb_transport(usb_handle * usb,const char * serial,unsigned writeable)702 void register_usb_transport(usb_handle *usb, const char *serial, unsigned writeable)
703 {
704     atransport *t = calloc(1, sizeof(atransport));
705     D("transport: %p init'ing for usb_handle %p (sn='%s')\n", t, usb,
706       serial ? serial : "");
707     init_usb_transport(t, usb, (writeable ? CS_OFFLINE : CS_NOPERM));
708     if(serial) {
709         t->serial = strdup(serial);
710     }
711     register_transport(t);
712 }
713 
714 /* this should only be used for transports with connection_state == CS_NOPERM */
unregister_usb_transport(usb_handle * usb)715 void unregister_usb_transport(usb_handle *usb)
716 {
717     atransport *t;
718     adb_mutex_lock(&transport_lock);
719     for(t = transport_list.next; t != &transport_list; t = t->next) {
720         if (t->usb == usb && t->connection_state == CS_NOPERM) {
721             t->next->prev = t->prev;
722             t->prev->next = t->next;
723             break;
724         }
725      }
726     adb_mutex_unlock(&transport_lock);
727 }
728 
729 #undef TRACE_TAG
730 #define TRACE_TAG  TRACE_RWX
731 
readx(int fd,void * ptr,size_t len)732 int readx(int fd, void *ptr, size_t len)
733 {
734     char *p = ptr;
735     int r;
736 #if ADB_TRACE
737     int  len0 = len;
738 #endif
739     D("readx: fd=%d wanted=%d\n", fd, (int)len);
740     while(len > 0) {
741         r = adb_read(fd, p, len);
742         if(r > 0) {
743             len -= r;
744             p += r;
745         } else {
746             if (r < 0) {
747                 D("readx: fd=%d error %d: %s\n", fd, errno, strerror(errno));
748                 if (errno == EINTR)
749                     continue;
750             } else {
751                 D("readx: fd=%d disconnected\n", fd);
752             }
753             return -1;
754         }
755     }
756 
757 #if ADB_TRACE
758     D("readx: fd=%d wanted=%d got=%d\n", fd, len0, len0 - len);
759     dump_hex( ptr, len0 );
760 #endif
761     return 0;
762 }
763 
writex(int fd,const void * ptr,size_t len)764 int writex(int fd, const void *ptr, size_t len)
765 {
766     char *p = (char*) ptr;
767     int r;
768 
769 #if ADB_TRACE
770     D("writex: fd=%d len=%d: ", fd, (int)len);
771     dump_hex( ptr, len );
772 #endif
773     while(len > 0) {
774         r = adb_write(fd, p, len);
775         if(r > 0) {
776             len -= r;
777             p += r;
778         } else {
779             if (r < 0) {
780                 D("writex: fd=%d error %d: %s\n", fd, errno, strerror(errno));
781                 if (errno == EINTR)
782                     continue;
783             } else {
784                 D("writex: fd=%d disconnected\n", fd);
785             }
786             return -1;
787         }
788     }
789     return 0;
790 }
791 
check_header(apacket * p)792 int check_header(apacket *p)
793 {
794     if(p->msg.magic != (p->msg.command ^ 0xffffffff)) {
795         D("check_header(): invalid magic\n");
796         return -1;
797     }
798 
799     if(p->msg.data_length > MAX_PAYLOAD) {
800         D("check_header(): %d > MAX_PAYLOAD\n", p->msg.data_length);
801         return -1;
802     }
803 
804     return 0;
805 }
806 
check_data(apacket * p)807 int check_data(apacket *p)
808 {
809     unsigned count, sum;
810     unsigned char *x;
811 
812     count = p->msg.data_length;
813     x = p->data;
814     sum = 0;
815     while(count-- > 0) {
816         sum += *x++;
817     }
818 
819     if(sum != p->msg.data_check) {
820         return -1;
821     } else {
822         return 0;
823     }
824 }
825