Browse Source

refactor code

Signed-off-by: surenyi <surenyi@gmail.com>
master
surenyi 9 years ago
parent
commit
9e2633ff82
  1. 10
      AlarmProvider.h
  2. 170
      AudioBridge.cpp
  3. 95
      AudioBridge.h
  4. 23
      AudioProvider.h
  5. 17
      CRC32.h
  6. 85
      CharConv.cpp
  7. 24
      CharConv.h
  8. 6
      IdMapper.c
  9. 7
      IdMapper.h
  10. 200
      Lan.cpp
  11. 15
      PTTProvider.h
  12. 186
      Runtime.cpp
  13. 52
      Runtime.h
  14. 35
      Timer.cpp
  15. 18
      Timer.h
  16. 28
      Udp.h
  17. 41
      UdpEvent.cpp
  18. 33
      UdpEvent.h
  19. 26
      UdpReadable.cpp
  20. 23
      UdpReadable.h
  21. 112
      Wan.cpp
  22. 124
      char_conv.c
  23. 11
      char_conv.h
  24. 237
      codec.c
  25. 77
      codec.h
  26. 28
      crc.c
  27. 7
      crc.h
  28. 239
      lan.c
  29. 117
      lan.h
  30. 12
      log.c
  31. 7
      log.h
  32. 10
      main.c
  33. 15
      main.cpp
  34. 10
      makefile
  35. 174
      runtime.c
  36. 43
      runtime.h
  37. 45
      timer.c
  38. 17
      timer.h
  39. 144
      udp.c
  40. 18
      udp.h
  41. 33
      udp_readable.c
  42. 17
      udp_readable.h
  43. 181
      wan.c
  44. 43
      wan.h

10
AlarmProvider.h

@ -1,10 +0,0 @@
#ifndef __ALARM_PROVIDER_H__
#define __ALARM_PROVIDER_H__
class AlarmProvider {
public:
void onAlarm(const char *str, int len);
};
#endif

170
AudioBridge.cpp

@ -1,170 +0,0 @@
#include <errno.h>
#include <string.h>
#include <time.h>
#include "UdpEvent.h"
#include "Log.h"
#include "Wan.h"
#include "Lan.h"
#include "IdMapper.h"
#include "AudioBridge.h"
class AudioUpEvent : public UdpEvent {
private:
AudioBridge *_bge;
public:
AudioUpEvent(Udp u, AudioBridge *_b) : UdpEvent(u), _bge(_b){}
void onEvent(int /* fd */, short what)
{
uint8_t buf[1500] = {0};
/* send to uplink */
if (what & UDP_READ) {
int n = _udp.recv(buf, sizeof buf);
if (n > 0)
_bge->onUpComplete(buf, n);
}
}
};
class AudioDownEvent : public UdpEvent {
private:
AudioBridge *_bge;
public:
AudioDownEvent(Udp u, AudioBridge *_b) : UdpEvent(u), _bge(_b){}
void onEvent(int /* fd */, short what)
{
if (what & UDP_READ) {
uint8_t buf[700] = {0};
int n = _udp.recv(buf, sizeof buf);
if (n > 0)
_bge->onDownComplete(buf, n);
}
/* send to downlink */
}
};
AudioBridge::AudioBridge()
:_uplink(0), _downlink(0), _downProvider(0), _upProvider(0), _audioEncType(AUDIO_ENC_ALL)
{
_encSeq = 0;
_decSeq = 0;
}
uint8_t AudioBridge::getCheckNum(uint8_t *buf, int len)
{
uint32_t sum = 0;
for (int i = 0; i < len; ++i) {
sum += buf[i];
}
return (sum & 0xff);
}
void AudioBridge::onUpAudio(struct MsgAudio *audio)
{
memset(&_encBuf, 0, sizeof _encBuf);
_encBuf.id1 = 0xAC;
_encBuf.id2 = 0x93;
_encBuf.id3 = 0x27;
_encBuf.id4 = 0x21;
_encBuf.swId = 0xB1;
_encBuf.fromId = 0xD8;
_encBuf.toId = 0xFF;
_encBuf.toSwId = 0xE2;
_encBuf.origPosId = IdMapper::getMappedWanId(audio->sender);
_encBuf.encType = _audioEncType;
_encBuf.contentId = 0xED;
_encBuf.flyType = 0;
_encBuf.flyId = 0;
/* XXX: here need to convert */
size_t len = audio->payloadLen;
if (len > sizeof _encBuf.payload)
len = sizeof _encBuf.payload;
memcpy(_encBuf.payload, audio->payload, len);
_encBuf.timeStamp = htonl(time(NULL));
_encBuf.seqNum = htonl(++_encSeq);
_encBuf.checkNum = getCheckNum((uint8_t *)&_encBuf, sizeof _encBuf - 2);
_encBuf.id5 = 0x14;
_uplink->getUdp().send(&_encBuf, sizeof _encBuf);
}
void AudioBridge::onDownAudio(struct WanAudioType *wat)
{
memset(&_decBuf, 0, sizeof _decBuf);
_decBuf.id1 = 0xAC;
_decBuf.id2 = 0x93;
_decBuf.id3 = 0x27;
_decBuf.id4 = 0x21;
_decBuf.swId = 0xB1;
_decBuf.origSwId = 0xD8;
_decBuf.toId = 0xFF;
_decBuf.toSwId = 0xE2;
_decBuf.origPosId = 0xB1;
_decBuf.encType = _audioEncType;
_decBuf.contentId = 0xED;
_decBuf.flyType = wat->apType;
_decBuf.flyId = wat->apId;
memcpy(_decBuf.payload, wat->mgrAudio, 6);
memcpy(_decBuf.auxPayload, wat->auxAudio, 6);
_decBuf.timeStamp = htonl(time(NULL));
_decBuf.seqNum = htonl(++_decSeq);
_decBuf.checkNum = getCheckNum((uint8_t *)&_decBuf, sizeof _decBuf - 2);
_decBuf.id5 = 0x14;
_downlink->getUdp().send((uint8_t *)&_decBuf, sizeof _decBuf);
}
int AudioBridge::__makeLink(Udp & _u, const char *bridge_ip, int bridge_port, const char *local_ip, int local_port)
{
if (_u.open() < 0) {
Log.printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__);
return -1;
}
if (_u.bind(local_ip, local_port) < 0) {
Log.printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, local_ip, local_port, errno, strerror(errno));
_u.close();
return -2;
}
if (_u.connect(bridge_ip, bridge_port) < 0) {
Log.printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, local_ip, local_port);
_u.close();
return -3;
}
return 0;
}
int AudioBridge::begin(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port)
{
Udp d, u;
if (__makeLink(d, bridge_ip, bridge_port, local_ip, down_port) < 0) {
return -1;
}
if (__makeLink(u, bridge_ip, bridge_port, local_ip, up_port) < 0) {
d.close();
return -2;
}
_downlink = new AudioDownEvent(d, this);
_uplink = new AudioUpEvent(u, this);
return 0;
}
void AudioBridge::onUpComplete(uint8_t *data, int len)
{
if (_upProvider)
_upProvider->onComplete(data, len);
}
void AudioBridge::onDownComplete(uint8_t *data, int len)
{
if (_downProvider)
_downProvider->onComplete(data, len);
}

95
AudioBridge.h

@ -1,95 +0,0 @@
#ifndef __AUDIO_BRIDGE_H__
#define __AUDIO_BRIDGE_H__
#include <stdint.h>
#include "AudioProvider.h"
#include "UdpReadable.h"
#define AUDIO_ENC_ALL 0x00
#define AUDIO_ENC_10 0x01
#define AUDIO_ENC_712 0x02
#define AUDIO_ENC_PKT_LEN (666)
#define AUDIO_DEC_PKT_LEN (64)
struct AudioEncType {
uint8_t id1;
uint8_t id2;
uint8_t id3;
uint8_t id4;
uint16_t resv0;
uint8_t swId;
uint8_t fromId;
uint8_t toId;
uint8_t toSwId;
uint8_t origPosId;
uint8_t resv1;
uint8_t encType;
uint8_t contentId;
uint8_t flyType;
uint8_t flyId;
uint8_t payload[640];
uint32_t timeStamp;
uint32_t seqNum;
uint8_t checkNum;
uint8_t id5;
} __attribute__((packed));
struct AudioDecInType {
uint8_t id1;
uint8_t id2;
uint8_t id3;
uint8_t id4;
uint16_t resv0;
uint8_t swId;
uint8_t origSwId;
uint8_t toId;
uint8_t toSwId;
uint8_t origPosId;
uint8_t resv1;
uint8_t encType;
uint8_t contentId;
uint8_t flyType;
uint8_t flyId;
uint8_t payload[6];
uint8_t auxPayload[6];
uint8_t resv2[26];
uint32_t timeStamp;
uint32_t seqNum;
uint8_t checkNum;
uint8_t id5;
} __attribute((packed));
class UdpEvent;
class Udp;
class AudioBridge : public AudioUpProvider, public AudioDownProvider {
private:
UdpEvent *_uplink;
UdpEvent *_downlink;
AudioCompleteProvider *_downProvider;
AudioCompleteProvider *_upProvider;
uint8_t _audioEncType;
AudioEncType _encBuf;
uint32_t _encSeq;
AudioDecInType _decBuf;
uint32_t _decSeq;
int __makeLink(Udp & _u, const char *brige_ip, int bridge_port, const char *local_ip, int local_port);
uint8_t getCheckNum(uint8_t *buf, int len);
public:
AudioBridge();
virtual void onUpAudio(struct MsgAudio *);
virtual void onDownAudio(struct WanAudioType *);
int begin(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port);
void setAudioEncType(uint8_t type) { _audioEncType = type;}
void setUpCompleteProvider(AudioCompleteProvider *_p) {_upProvider = _p;}
void setDownCompleteProvider(AudioCompleteProvider *_p) {_downProvider = _p;}
void onDownComplete(uint8_t *data, int len);
void onUpComplete(uint8_t *data, int len);
};
#endif

23
AudioProvider.h

@ -1,23 +0,0 @@
#ifndef __AUDIO__PROVIDER_H__
#define __AUDIO__PROVIDER_H__
struct MsgAudio;
struct WanAudioType;
class AudioUpProvider {
public:
virtual void onUpAudio(MsgAudio * audio) = 0;
};
class AudioDownProvider {
public:
virtual void onDownAudio(struct WanAudioType *) = 0;
};
class AudioCompleteProvider {
public:
virtual void onComplete(uint8_t *buf, int len) = 0;
};
#endif

17
CRC32.h

@ -1,17 +0,0 @@
#ifndef __CRC32_H__
#define __CRC32_H__
#include <stdint.h>
class Crc32 {
private:
unsigned int crc_table[256];
void init();
uint32_t doCrc(uint32_t crc,unsigned char *buffer, unsigned int size);
public:
Crc32();
uint32_t crc(uint8_t *data, int len);
};
#endif

85
CharConv.cpp

@ -1,85 +0,0 @@
#include <errno.h>
#include <string.h>
#include "CharConv.h"
#include "UdpEvent.h"
#include "Runtime.h"
#include "Lan.h"
#include "Log.h"
#define LOIFADDR "127.0.0.1"
void CharConv::isReadable(Udp &u)
{
uint8_t buf[1560] = {0};
int len;
Log.printf("char readable\n");
if ((len = u.recv(buf, sizeof buf)) <= 0)
return;
Log.printf("char conv recv: %d bytes\n", len);
/* XXX : packetizing ... */
Runtime.getLan().send(buf, len);
}
int CharConv::begin(int to_port, int from_port)
{
Udp u;
if (u.open() < 0) {
Log.printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__);
return -1;
}
if (u.bind(LOIFADDR, from_port) < 0) {
Log.printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, LOIFADDR, from_port, errno, strerror(errno));
u.close();
return -2;
}
if (u.connect(LOIFADDR, to_port) < 0) {
Log.printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, LOIFADDR, to_port);
u.close();
return -3;
}
UdpReadable::begin(u);
_cd = iconv_open("GB2312", "UTF-8");
if (_cd == (iconv_t)-1) {
Log.printf("can't crate iconv conventer\n");
}
return 0;
}
void CharConv::onAlarm(const char *str, int len)
{
uint8_t buf[1500] = {0};
int idx = 0;
Log.printf("alarm: %d, %s\n", len, str);
buf[idx++] = 0x68;
buf[idx++] = 0x00;
buf[idx++] = 0x00;
buf[idx++] = 0x80;
buf[idx++] = len & 0xff;
buf[idx++] = (len >> 8) & 0xff;
memcpy(buf + idx, str, len);
idx += len;
uint32_t cs = _crc.crc((uint8_t *)str, len);
buf[idx++] = cs & 0xff;
buf[idx++] = (cs >> 8) & 0xff;
buf[idx++] = (cs >> 16) & 0xff;
buf[idx++] = (cs >> 24) & 0xff;
int n = _udp.send(buf, idx);
Log.printf("conv sending: %d bytes\n", n);
}
void CharConv::end()
{
if (_cd != (iconv_t)-1) {
iconv_close(_cd);
_cd = (iconv_t)-1;
}
_udp.close();
}

24
CharConv.h

@ -1,24 +0,0 @@
#ifndef __CHAR_CONV_H__
#define __CHAR_CONV_H__
#include <iconv.h>
#include "AlarmProvider.h"
#include "UdpReadable.h"
#include "CRC32.h"
class CharConv : public AlarmProvider, public UdpReadable {
private:
Crc32 _crc;
iconv_t _cd;
public:
int begin(int to_port, int from_port);
void onAlarm(const char *str, int len);
virtual void isReadable(Udp &u);
void end();
~CharConv() {
end();
}
};
#endif

6
IdMapper.cpp → IdMapper.c

@ -1,4 +1,4 @@
#include "Lan.h" #include "lan.h"
#include "IdMapper.h" #include "IdMapper.h"
struct Idmap { struct Idmap {
@ -15,7 +15,7 @@ static struct Idmap idmap[NOOFTERMS] = {
{0xFD, 0x06} {0xFD, 0x06}
}; };
uint8_t IdMapper::getMappedWanId(uint8_t id) uint8_t getMappedWanId(uint8_t id)
{ {
for (int i = 0; i < NOOFTERMS; ++i) { for (int i = 0; i < NOOFTERMS; ++i) {
if (idmap[i].lanId == id) { if (idmap[i].lanId == id) {
@ -25,7 +25,7 @@ uint8_t IdMapper::getMappedWanId(uint8_t id)
return 0; return 0;
} }
uint8_t IdMapper::getMappedLanId(uint8_t id) uint8_t getMappedLanId(uint8_t id)
{ {
for (int i = 0; i < NOOFTERMS; ++i) { for (int i = 0; i < NOOFTERMS; ++i) {
if (idmap[i].wanId == id) { if (idmap[i].wanId == id) {

7
IdMapper.h

@ -2,13 +2,10 @@
#define __IDMAPPER_H__ #define __IDMAPPER_H__
#include <stdint.h> #include <stdint.h>
class IdMapper {
public:
/* convert lan id to wan id */ /* convert lan id to wan id */
static uint8_t getMappedWanId(uint8_t id); uint8_t getMappedWanId(uint8_t id);
/* convert wna id to lan id */ /* convert wna id to lan id */
static uint8_t getMappedLanId(uint8_t id); uint8_t getMappedLanId(uint8_t id);
};
#endif #endif

200
Lan.cpp

@ -1,200 +0,0 @@
#include <unistd.h>
#include <string.h>
#include "IdMapper.h"
#include "UdpEvent.h"
#include "AudioBridge.h"
#include "Lan.h"
#include "Log.h"
#define LAN_PKT_MIN_LEN (16)
#define LAN_PKT_MAX_LEN (256)
int Lan::begin(const char *group_addr, int port, const char *local_if)
{
Udp udp;
#if 0
Log.printf("struct MsgCmd: %d\n", sizeof (struct MsgCmd));
Log.printf("struct MsgTermStatus: %d\n", sizeof (struct MsgTermStatus));
Log.printf("struct MsgAudio: %d\n", sizeof (struct MsgAudio));
Log.printf("struct MsgAlarm: %d\n", sizeof (struct MsgAlarm));
#endif
if (udp.open() < 0) {
Log.printf("'%s[%d]: can't create Lan socket\n", __func__, __LINE__);
return -1;
}
Log.printf("local: %s, %s, %d\n", local_if, group_addr, port);
if (udp.bind(local_if, port) < 0) {
Log.printf("'%s[%d]: can't bind Lan socket\n", __func__, __LINE__);
udp.close();
return -2;
}
if (udp.connect(group_addr, port) < 0) {
Log.printf("'%s[%d]: can't connect Lan socket\n", __func__, __LINE__);
udp.close();
return -3;
}
UdpReadable::begin(udp);
_myseq = 0;
return 0;
}
void Lan::doCmd(uint8_t *buf, int len)
{
struct MsgCmd hdr, *sdp;
struct MsgTermStatus *mts;
uint8_t out;
uint16_t cmd;
sdp = (struct MsgCmd *)(buf);
hdr = *sdp;
cmd = ntohs(hdr.msgCmd);
// Log.printf("Lan cmd [%02x]\n", cmd);
switch (cmd) {
case MSG_CMD_HANDSHAKE:
hdr.sender = sdp->recver;
hdr.recver = sdp->sender;
hdr.msgCmd = htons(MSG_RES_HANDSHAKE);
#if 0
do {
uint8_t *dp;
dp = (uint8_t *)&hdr;
for (int x= 0; x < 12; ++x) {
Log.printf("%02x ", dp[x]);
}
Log.printf("\n");
} while (0);
#endif
send(&hdr, sizeof hdr);
len -= sizeof hdr;
buf += sizeof hdr;
/* 6 x 4 bytes:
* 0 1 2 3
* id downlink ptt alarm
*/
while (len > (int)sizeof (*mts)) {
mts = (struct MsgTermStatus *)buf;
out = IdMapper::getMappedWanId(mts->termId);
if (out > 0) {
_provider->onStatus(out, mts->isAlarm);
}
len -= sizeof (*mts);
buf += sizeof (*mts);
}
break;
case MSG_CMD_PTTON:
out = IdMapper::getMappedWanId(hdr.sender);
if (out > 0) {
_provider->onPTT(this, &hdr, out, true);
}
break;
case MSG_CMD_PTTOFF:
out = IdMapper::getMappedWanId(hdr.sender);
if (out > 0) {
_provider->onPTT(this, &hdr, out, false);
}
break;
}
}
void Lan::doAudio(uint8_t *buf, int len)
{
struct MsgAudio *laph;
if (len < (int)(sizeof *laph))
return;
laph = (struct MsgAudio *)(buf);
laph->payloadLen = ntohl(laph->payloadLen);
if (len < (int)(sizeof *laph + laph->payloadLen)) {
Log.printf("audio length too small, total: %d, payload: %d\n", len, laph->payloadLen);
return;
}
Log.printf("recver< %d >: %x, sender: %x, mode: %d, recvChannel: %d, sendChannel: %d\n",
laph->payloadLen, laph->recver, laph->sender, laph->mode, laph->recvChannel, laph->sendChannel);
_audioUp->onUpAudio(laph);
}
void Lan::isReadable(Udp & _u)
{
uint8_t buf[LAN_PKT_MAX_LEN] = {0};
int len;
if ((len = _u.recv(buf, sizeof buf)) < LAN_PKT_MIN_LEN)
return;
#if 0
do {
Log.printf("Lan: %d bytes\n", len);
for (int x = 0; x < len; ++x) {
Log.printf("%02x%c", buf[x], ((x + 1) % 16) ? ' ' : '\n');
}
Log.printf("\n");
} while (0);
#endif
switch (buf[0]) {
case MSG_TYPE_CMD:
doCmd(buf, len);
break;
case MSG_TYPE_AUDIO:
doAudio(buf, len);
break;
case MSG_TYPE_ALARM:
break;
}
}
void Lan::onComplete(uint8_t *buf, int len)
{
struct AudioEncType *aet;
struct MsgAudio *ma;
uint8_t msg[MSG_AUDIO_LEN] = {0};
if (len < (int)(sizeof *aet)) {
Log.printf("Audio too short.\n");
return;
}
ma = (struct MsgAudio *)(msg);
aet = (struct AudioEncType *)(buf);
ma->type = MSG_TYPE_AUDIO;
ma->recver = 0x19;
ma->sender = 0x07;
ma->swid = 0xB1;
ma->seqNum = htonl(++_myseq);
ma->payloadLen = 160;
/*XXX: transcode aet->payload */
memcpy(ma->payload, aet->payload, ma->payloadLen);
send(msg, sizeof msg);
}
int Lan::onResponse(int resp_type, struct MsgCmd *hdr, int status)
{
struct MsgCmd pkt;
pkt = *hdr;
pkt.recver = hdr->sender;
pkt.sender = hdr->recver;
switch (resp_type) {
case RESP_PTT_ON:
if (status == RESP_PTT_OK) {
pkt.msgCmd = htons(MSG_RES_PTTON);
} else {
pkt.msgCmd = htons(MSG_REFUSE_PTTON);
}
break;
case RESP_PTT_OFF:
pkt.msgCmd = htons(MSG_RES_PTTOFF);
break;
}
send(&pkt, sizeof pkt);
return 0;
}

15
PTTProvider.h

@ -1,15 +0,0 @@
#ifndef __PTTPROVIDER_H__
#define __PTTPROVIDER_H__
#include <stdint.h>
class Lan;
struct MsgCmd;
class PTTProvider {
public:
virtual void onPTT(Lan *, struct MsgCmd *hdr, uint8_t posId, bool on) = 0;
virtual void onStatus(uint8_t id, uint8_t status) = 0;
};
#endif

186
Runtime.cpp

@ -1,186 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "Runtime.h"
#include "Log.h"
#include "Udp.h"
#include "Timer.h"
#define LAN_IF "eth0"
#define LAN_FROM "192.168.9.25"
#define LAN_PORT 5600
#define BGE_IP "192.168.9.19"
#define BGE_PORT 6419
#define BGE_UP_PORT 6402
#define BGE_DOWN_PORT 6400
/*
* Please disable rp_filter
* edit /etc/sysctl.conf
*
* net.ipv4.conf.default.rp_filter = 0
* net.ipv4.conf.all.rp_filter = 0
*
* add route for eth1
* route add -net 192.168.31.0/24 dev eth1
*/
#if 1
#define WAN_IF "eth1"
#define WAN_GROUP "225.0.0.5"
#define WAN_GROUP_PORT 8300
#define WAN_STATUS_PORT 8100
#else
#define WAN_IF "eth0"
#define WAN_GROUP "224.0.0.24"
#define WAN_GROUP_PORT 8300
#define WAN_STATUS_PORT 5100
#endif
Runtime::Runtime()
{
struct event_config *config;
_lan_if = (char *)LAN_IF;
_lan_grp_addr = (char *)LAN_FROM;
_lan_grp_port = LAN_PORT;
_bge_ip = (char *)BGE_IP;
_bge_port = BGE_PORT;
_up_port = BGE_UP_PORT;
_down_port = BGE_DOWN_PORT;
_wan_if = (char *)WAN_IF;
_wan_grp_addr = (char *)WAN_GROUP;
_wan_grp_port = WAN_GROUP_PORT;
_wan_status_port = WAN_STATUS_PORT;
config = event_config_new();
event_config_avoid_method(config, "select");
event_config_require_features(config, EV_FEATURE_ET);
_evbase = event_base_new_with_config(config);
event_config_free(config);
}
int Runtime::loop()
{
return event_base_dispatch(_evbase);
}
void Runtime::printHelp()
{
fprintf(stderr, "usage: cmd [option], options as:\n\t"
"--lanif, -l: set lan ethx interface, eg: \"ethx\"\n\t"
"--landest, -g: set lan multicast address, eg: \"192.168.9.25\"\n\t"
"--lanport, -p: set lan multicast port, eg: 5600\n\t"
"--wanif, -w: set lan ethx interface, eg: \"ethx\"\n\t"
"--wangrp, -r: set lan multicast address, eg: \"255.0.0.5\"\n\t"
"--wanport, -t: set lan multicast port, eg: 5600\n\t"
"--help, -h: print this message.\n");
}
void Runtime::parseArgs(int argc, char *argv[])
{
int c;
static struct option options[] = {
{"lanif", required_argument, NULL, 'l'},
{"landest", required_argument, NULL, 'g'},
{"lanport", required_argument, NULL, 'p'},
{"wanif", required_argument, NULL, 'w'},
{"wangrp", required_argument, NULL, 'r'},
{"wanport", required_argument, NULL, 't'},
{"wanstport", required_argument, NULL, 'o'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
while ((c = getopt_long(argc, argv, "l:g:p:w:r:t:o:h", options, NULL)) != -1) {
switch (c) {
case 'l':
_lan_if = optarg;
break;
case 'g':
_lan_grp_addr = optarg;
break;
case 'p':
_lan_grp_port = atoi(optarg);
break;
case 'w':
_wan_if = optarg;
break;
case 'r':
_wan_grp_addr = optarg;
case 't':
_wan_grp_port = atoi(optarg);
break;
case 'o':
_wan_status_port = atoi(optarg);
break;
case 'h':
printHelp();
exit(0);
}
}
}
class AlarmTimer : public Timer {
private:
CharConv *_c;
int count;
public:
AlarmTimer(CharConv *c) : _c(c), count(0){}
virtual void onTimer()
{
char buf[128];
snprintf(buf, sizeof buf, "数量这么多数据还是不错");
_c->onAlarm(buf, strlen(buf));
}
};
void Runtime::begin()
{
char local_if[64] = {0};
char wan_if[64] = {0};
Log.begin();
Udp::getip(_lan_if, local_if, sizeof local_if);
if (_lan.begin(_lan_grp_addr, _lan_grp_port, local_if) < 0) {
Log.printf("lan initialize failed.\n");
exit(-1);
}
if (_abge.begin(_bge_ip, _bge_port, local_if, _down_port, _up_port) < 0) {
Log.printf("audio bridge initialize failed.\n");
exit(-2);
}
Udp::getip(_wan_if, wan_if, sizeof wan_if);
if (_wan.begin(_wan_grp_addr, _wan_grp_port, wan_if, _wan_status_port) < 0) {
Log.printf("wan initialize failed.\n");
exit(-3);
}
if (_conv.begin(6801, 6802) < 0) {
Log.printf("char convter initiazlie failed.\n");
exit(-4);
}
#if 1
static AlarmTimer at(&_conv);
at.begin();
at.active(1000);
#endif
_abge.setDownCompleteProvider(&_lan);
_abge.setUpCompleteProvider(&_wan);
_lan.setAudioUpProvider(&_abge);
_wan.setAudioDownProvider(&_abge);
_lan.setPTTProvider(&_wan);
_wan.setAlarmProvider(&_conv);
}
class Runtime Runtime;

52
Runtime.h

@ -1,52 +0,0 @@
#ifndef __RUNTIME_H____
#define __RUNTIME_H____
#include <event2/event.h>
#include "Lan.h"
#include "Wan.h"
#include "AudioBridge.h"
#include "CharConv.h"
class Runtime {
private:
struct event_base *_evbase;
/* lan config */
Lan _lan;
char *_lan_if;
char *_lan_grp_addr;
int _lan_grp_port;
/* audio bridge */
AudioBridge _abge;
char *_bge_ip;
int _bge_port;
int _up_port;
int _down_port;
/* Wan */
Wan _wan;
char *_wan_if;
char *_wan_grp_addr;
int _wan_grp_port;
int _wan_status_port;
CharConv _conv;
void printHelp();
public:
Runtime();
void parseArgs(int argc, char *argv[]);
void begin();
Lan & getLan() { return _lan;}
struct event_base *getEvBase() const { return _evbase;}
int loop();
};
extern class Runtime Runtime;
#endif

35
Timer.cpp

@ -1,35 +0,0 @@
#include "Timer.h"
#include "Log.h"
#include "Runtime.h"
void Timer::__helper(int , short, void *arg)
{
Timer *t = static_cast<Timer *>(arg);
t->onTimer();
}
void Timer::onTimer()
{
Log.printf("dummy timer\n");
}
void Timer::begin()
{
event_assign(&_evt, Runtime.getEvBase(), -1, EV_TIMEOUT | EV_PERSIST, __helper, this);
}
void Timer::active(int ms)
{
struct timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = ms % 1000;
event_add(&_evt, &tv);
}
void Timer::deactive()
{
event_del(&_evt);
}

18
Timer.h

@ -1,18 +0,0 @@
#ifndef __ETIMER_H__
#define __ETIMER_H__
#include <event2/event.h>
#include <event2/event_struct.h>
class Timer {
private:
struct event _evt;
static void __helper(int fd, short what, void *arg);
public:
void begin();
void active(int us);
void deactive();
virtual void onTimer();
};
#endif

28
Udp.h

@ -1,28 +0,0 @@
#ifndef __UDP_H___
#define __UDP_H___
#include <netinet/in.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
class Udp {
protected:
int sock;
struct sockaddr_in destAddr;
bool isMcast;
public:
Udp();
Udp(const Udp &_u) { sock = _u.sock;}
int getFd() { return sock;}
int open();
int send(const void *buf, int len);
int recv(void *buf, int len);
int openMulticast(const char *group, int port, const char *local);
int bind(const char *ip_dot, int port);
int connect(const char *to, int to_port);
int close();
static int getip(const char *ethx, char *ip_dot, int len);
};
#endif

41
UdpEvent.cpp

@ -1,41 +0,0 @@
#include "Udp.h"
#include "UdpEvent.h"
#include "Log.h"
#include "Runtime.h"
UdpEvent::~UdpEvent()
{
if (_evt) {
end();
}
_udp.close();
}
void UdpEvent::__helper(int fd, short what, void *arg)
{
UdpEvent *ue = static_cast<UdpEvent*>(arg);
ue->onEvent(fd, what);
}
void UdpEvent::end()
{
event_del(_evt);
event_free(_evt);
_evt = NULL;
}
int UdpEvent::begin(int flag, bool oneshot)
{
if (!oneshot)
flag |= EV_PERSIST;
Log.printf("flag: %02x, fd: %d\n", flag, _udp.getFd());
_evt = event_new(Runtime.getEvBase(), _udp.getFd(), flag, __helper, this);
if (_evt) {
event_add(_evt, NULL);
return 0;
}
return -1;
}

33
UdpEvent.h

@ -1,33 +0,0 @@
#ifndef __UDPEVENT_H__
#define __UDPEVENT_H__
#include <event2/event.h>
#include "Udp.h"
class UdpEvent {
protected:
Udp _udp;
struct event *_evt;
private:
static void __helper(int fd, short what, void *arg);
public:
enum {UDP_READ = EV_READ, UDP_WRITE = EV_WRITE};
UdpEvent() : _evt(0){}
UdpEvent(Udp _u) : _udp(_u), _evt(0) {}
int begin(Udp udp, int type, bool onshot = false);
int begin(int type, bool oneshot = false);
void end();
Udp & getUdp(){return _udp;}
virtual void onEvent(int , short) = 0;
virtual ~UdpEvent();
};
#endif

26
UdpReadable.cpp

@ -1,26 +0,0 @@
#include "Udp.h"
#include "UdpReadable.h"
#include "Log.h"
#include "Runtime.h"
void UdpReadable::__helper(int /* fd */, short what, void *arg)
{
UdpReadable *p = static_cast<UdpReadable *>(arg);
if (what & EV_READ) {
p->isReadable(p->_udp);
}
}
int UdpReadable::begin(const Udp &udp)
{
_udp = udp;
event_assign(&_evt, Runtime.getEvBase(), _udp.getFd(), EV_READ | EV_PERSIST, __helper, this);
event_add(&_evt, NULL);
return 0;
}
void UdpReadable::end()
{
event_del(&_evt);
}

23
UdpReadable.h

@ -1,23 +0,0 @@
#ifndef __UDPREDABLE_H__
#define __UDPREDABLE_H__
#include <event2/event.h>
#include <event2/event_struct.h>
#include "Udp.h"
class UdpReadable {
protected:
Udp _udp;
private:
struct event _evt;
static void __helper(int fd, short what, void *arg);
public:
int begin(const Udp &udp);
void end();
virtual void isReadable(Udp &) = 0;
virtual ~UdpReadable() {end();}
};
#endif

112
Wan.cpp

@ -1,112 +0,0 @@
#include <time.h>
#include <errno.h>
#include <string.h>
#include "UdpEvent.h"
#include "Wan.h"
#include "Lan.h"
#include "Log.h"
int Wan::begin(const char *group_addr, int port, const char *wlan_if, int stport)
{
Udp udp;
Log.printf("Wan group: %s, port: %d, wan: %s\n", group_addr, port, wlan_if);
if (udp.openMulticast(group_addr, port, wlan_if) < 0) {
Log.printf("'%s[%d]: can't create multicast socket\n", __FILE__, __LINE__);
return -1;
}
if (_stSock.openMulticast(group_addr, stport, wlan_if) < 0) {
Log.printf("'%s[%d]: can't create status multicast socket\n", __FILE__, __LINE__);
udp.close();
return -2;
}
UdpReadable::begin(udp);
_stSeq = 0;
memset(&_stBuf, 0, sizeof _stBuf);
_stBuf.id1 = 0xAC;
_stBuf.id2 = 0x93;
_stBuf.id3 = 0x27;
_stBuf.id4 = 0x21;
_stBuf.srcPosId = 0xB1;
_stBuf.srcSwId = 0xD8;
_stBuf.destSwId = 0xE8;
_stBuf.initPosId = 0xB1;
_stBuf.contentId = 0xF3;
_stBuf.id5 = 0x14;
return 0;
}
void Wan::isReadable(Udp &u)
{
uint8_t data[1500] = {0};
int len;
if ((len = u.recv(data, sizeof data)) <= 0)
return;
#if 0
Log.printf("Wan recv: %d bytes\n", len);
for (int i = 0; i < len; ++i) {
Log.printf("%02x%c", data[i], ((i + 1) % 16) ? ' ' : '\n');
}
Log.printf("\n");
#endif
if ((data[0] == 0xAA) && (data[1] == 0x55)) {
if ((len == 32) && (data[6] == 0x91)) {
struct WanAudioType *wat = (struct WanAudioType *)data;
_audioDown->onDownAudio(wat);
}
}
/*XXX: if alarming , call _alarm->onAlarm() */
if ((data[0] == 0xAC) && (data[1] == 0x93)) {
if ((len == 64) && (data[13] == 0xF0)) {
}
}
}
void Wan::onPTT(Lan *ln, struct MsgCmd *hdr, uint8_t posId, bool on)
{
if (on) {
} else {
}
ln->onResponse(on ? Lan::RESP_PTT_ON : Lan::RESP_PTT_OFF, hdr, RESP_PTT_OK);
}
void Wan::onComplete(uint8_t *buf, int len)
{
_udp.send(buf, len);
}
void Wan::onStatus(uint8_t id, uint8_t status)
{
int len = 0;
uint8_t *sbuf;
_stBuf.destId = status ? id : 0;
/*
* 0: don't start
* 1: playing
* 2: idle
*/
_stBuf.status = status ? 0x01 : 0x02;
_stBuf.time = htonl(time(NULL));
_stBuf.seq = htonl(++_stSeq);
uint32_t cs = 0;
len = sizeof _stBuf - 2;
sbuf = (uint8_t *)&_stBuf;
for (int x = 0; x < len; ++x) {
cs += sbuf[x];
}
_stBuf.checkNum = cs & 0xff;
len = _stSock.send(&_stBuf, sizeof _stBuf);
if (len < 0) {
Log.printf("%s:%d errno (%d) %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
// Log.printf("status sending %d bytes\n", len);
}

124
char_conv.c

@ -0,0 +1,124 @@
#include <errno.h>
#include <string.h>
#include <iconv.h>
#include "runtime.h"
#include "udp_readable.h"
#include "char_conv.h"
#include "log.h"
#include "crc.h"
struct alarm_handler {
struct wan_alarm_handler base;
char_conv_t *thiz;
};
struct char_conv {
struct udp_readable base;
struct alarm_handler alarm;
iconv_t cd;
};
#define LOIFADDR "127.0.0.1"
struct wan_alarm_handler *char_conv_get_alarm_handler(char_conv_t *cv)
{
return &cv->alarm.base;
}
static void __is_readable(udp_readable_t *ur)
{
uint8_t buf[1560] = {0};
int len;
char_conv_t *cv;
cv = (char_conv_t *)ur;
log_printf("char readable\n");
if ((len = ur->udp->recv(ur->udp, buf, sizeof buf)) <= 0)
return;
log_printf("char conv recv: %d bytes\n", len);
/* XXX : packetizing ... */
// Runtime.getLan().send(buf, len);
}
static void __on_alarm(struct wan_alarm_handler *self, struct WanAlarmType *wat)
{
uint8_t buf[1500] = {0};
int idx = 0;
size_t len;
unsigned int cs;
struct alarm_handler *ah = (struct alarm_handler *)self;
char_conv_t *cv = ah->thiz;
buf[idx++] = 0x68;
buf[idx++] = 0x00;
buf[idx++] = 0x00;
buf[idx++] = 0x80;
for (len = 0; len < sizeof wat->msg; ++len) {
if (wat->msg[len] == 0) {
break;
}
}
buf[idx++] = len & 0xff;
buf[idx++] = (len >> 8) & 0xff;
memcpy(buf + idx, wat->msg, len);
idx += len;
cs = crc(wat->msg, len);
buf[idx++] = cs & 0xff;
buf[idx++] = (cs >> 8) & 0xff;
buf[idx++] = (cs >> 16) & 0xff;
buf[idx++] = (cs >> 24) & 0xff;
do {
udp_t *_udp = cv->base.udp;
int n = _udp->send(_udp, buf, idx);
log_printf("conv sending: %d bytes\n", n);
} while (0);
}
char_conv_t *char_conv_new(int to_port, int from_port)
{
udp_t *u;
char_conv_t *cv;
if ((u = udp_open()) == NULL) {
log_printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__);
return NULL;
}
if (u->bind(u, LOIFADDR, from_port) < 0) {
log_printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, LOIFADDR, from_port, errno, strerror(errno));
u->close(u);
return NULL;
}
if (u->connect(u, LOIFADDR, to_port) < 0) {
log_printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, LOIFADDR, to_port);
u->close(u);
return NULL;
}
cv = (char_conv_t *)udp_readable_open(sizeof *cv, u);
cv->base.is_readable = __is_readable;
cv->cd = iconv_open("GB2312", "UTF-8");
if (cv->cd == (iconv_t)-1) {
log_printf("can't crate iconv conventer\n");
udp_readable_close(&cv->base);
return NULL;
}
cv->alarm.base.on_alarm = __on_alarm;
cv->alarm.thiz = cv;
return cv;
}
void char_conv_free(char_conv_t *cv)
{
iconv_close(cv->cd);
udp_readable_close(&cv->base);
}

11
char_conv.h

@ -0,0 +1,11 @@
#ifndef __CHAR_CONV_H__
#define __CHAR_CONV_H__
#include "wan.h"
typedef struct char_conv char_conv_t;
char_conv_t *char_conv_new(int to_port, int from_port);
struct wan_alarm_handler *char_conv_get_alarm_handler(char_conv_t *cv);
void char_conv_free(char_conv_t *cv);
#endif

237
codec.c

@ -0,0 +1,237 @@
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <time.h>
#include <stdint.h>
#include "codec.h"
#include "log.h"
#include "lan.h"
#include "wan.h"
#include "udp_readable.h"
#include "IdMapper.h"
struct uplink_audio_handler {
struct lan_audio_handler base;
codec_t *thiz;
};
struct downlink_audio_handler {
struct wan_audio_handler base;
codec_t *thiz;
};
struct udp_wrapper {
struct udp_readable base;
codec_t *thiz;
};
struct codec {
struct uplink_audio_handler _audio_up;
struct downlink_audio_handler _audio_down;
struct udp_wrapper *_uplink;
struct udp_wrapper *_downlink;
struct codec_complete *_up_complete;
struct codec_complete *_down_complete;
uint8_t _audioEncType;
struct AudioEncType _encBuf;
uint32_t _encSeq;
struct AudioDecInType _decBuf;
uint32_t _decSeq;
};
struct lan_audio_handler *codec_get_uplink_handler(codec_t *cc)
{
return &cc->_audio_up.base;
}
struct wan_audio_handler *codec_get_downlink_handler(codec_t *cc)
{
return &cc->_audio_down.base;
}
void codec_set_enc_type(codec_t *cc, int type)
{
cc->_audioEncType = type;
}
void codec_set_up_complete(codec_t *cc, struct codec_complete *ccp)
{
cc->_up_complete = ccp;
}
void codec_set_down_complete(codec_t *cc, struct codec_complete *ccp)
{
cc->_down_complete = ccp;
}
static uint8_t getcs(uint8_t *buf, int len)
{
uint32_t sum = 0;
for (int i = 0; i < len; ++i) {
sum += buf[i];
}
return (sum & 0xff);
}
static void __on_up_audio( struct lan_audio_handler *lh,
struct MsgAudio *audio)
{
struct uplink_audio_handler *uh = (struct uplink_audio_handler *)lh;
codec_t *cc = uh->thiz;
struct udp_wrapper *uw = cc->_uplink;
udp_t *u = uw->base.udp;
memset(&cc->_encBuf, 0, sizeof cc->_encBuf);
cc->_encBuf.id1 = 0xAC;
cc->_encBuf.id2 = 0x93;
cc->_encBuf.id3 = 0x27;
cc->_encBuf.id4 = 0x21;
cc->_encBuf.swId = 0xB1;
cc->_encBuf.fromId = 0xD8;
cc->_encBuf.toId = 0xFF;
cc->_encBuf.toSwId = 0xE2;
cc->_encBuf.origPosId = getMappedWanId(audio->sender);
cc->_encBuf.encType = cc->_audioEncType;
cc->_encBuf.contentId = 0xED;
cc->_encBuf.flyType = 0;
cc->_encBuf.flyId = 0;
/* XXX: here need to convert */
size_t len = audio->payloadLen;
if (len > sizeof cc->_encBuf.payload)
len = sizeof cc->_encBuf.payload;
memcpy(cc->_encBuf.payload, audio->payload, len);
cc->_encBuf.timeStamp = htonl(time(NULL));
cc->_encBuf.seqNum = htonl(++cc->_encSeq);
cc->_encBuf.checkNum = getcs((uint8_t *)&cc->_encBuf, sizeof cc->_encBuf - 2);
cc->_encBuf.id5 = 0x14;
u->send(u, &cc->_encBuf, sizeof cc->_encBuf);
}
static void __on_down_audio(struct wan_audio_handler *wh, struct WanAudioType *wat)
{
struct downlink_audio_handler *dh = (struct downlink_audio_handler *)wh;
codec_t *cc = dh->thiz;
struct udp_wrapper *uw = cc->_downlink;
udp_t *u = uw->base.udp;
memset(&cc->_decBuf, 0, sizeof cc->_decBuf);
cc->_decBuf.id1 = 0xAC;
cc->_decBuf.id2 = 0x93;
cc->_decBuf.id3 = 0x27;
cc->_decBuf.id4 = 0x21;
cc->_decBuf.swId = 0xB1;
cc->_decBuf.origSwId = 0xD8;
cc->_decBuf.toId = 0xFF;
cc->_decBuf.toSwId = 0xE2;
cc->_decBuf.origPosId = 0xB1;
cc->_decBuf.encType = cc->_audioEncType;
cc->_decBuf.contentId = 0xED;
cc->_decBuf.flyType = wat->apType;
cc->_decBuf.flyId = wat->apId;
memcpy(cc->_decBuf.payload, wat->mgrAudio, 6);
memcpy(cc->_decBuf.auxPayload, wat->auxAudio, 6);
cc->_decBuf.timeStamp = htonl(time(NULL));
cc->_decBuf.seqNum = htonl(++cc->_decSeq);
cc->_decBuf.checkNum = getcs((uint8_t *)&cc->_decBuf, sizeof cc->_decBuf - 2);
cc->_decBuf.id5 = 0x14;
u->send(u, (uint8_t *)&cc->_decBuf, sizeof cc->_decBuf);
}
static udp_t *__make_link(const char *bridge_ip, int bridge_port, const char *local_ip, int local_port)
{
udp_t *_u;
if ((_u = udp_open()) == NULL) {
log_printf("'%s[%d]: can't create socket\n", __FILE__, __LINE__);
return NULL;
}
if (_u->bind(_u, local_ip, local_port) < 0) {
log_printf("'%s[%d]: can't bind [%s:%d] socket (%d: %s)\n", __FILE__, __LINE__, local_ip, local_port, errno, strerror(errno));
_u->close(_u);
return NULL;
}
if (_u->connect(_u, bridge_ip, bridge_port) < 0) {
log_printf("'%s[%d]: can't connect [%s:%d] socket\n", __FILE__, __LINE__, local_ip, local_port);
_u->close(_u);
return NULL;
}
return _u;
}
static void __up_readable(udp_readable_t *ur)
{
int n;
uint8_t buf[1500] = {0};
struct udp_wrapper *uw = (struct udp_wrapper *)ur;
codec_t *cc = uw->thiz;
udp_t *u = ur->udp;
struct codec_complete *ccp = cc->_up_complete;
/* send to uplink */
if ((n = u->recv(u, buf, sizeof buf)) > 0) {
ccp->on_complete(ccp, buf, n);
}
}
static void __down_readable(udp_readable_t *ur)
{
int n;
uint8_t buf[1500] = {0};
struct udp_wrapper *uw = (struct udp_wrapper *)ur;
codec_t *cc = uw->thiz;
udp_t *u = ur->udp;
struct codec_complete *ccp = cc->_down_complete;
/* send to uplink */
if ((n = u->recv(u, buf, sizeof buf)) > 0) {
ccp->on_complete(ccp, buf, n);
}
}
codec_t *codec_new(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port)
{
codec_t *cc;
udp_t *d, *u;
if ((d = __make_link(bridge_ip, bridge_port, local_ip, down_port)) == NULL) {
return NULL;
}
if (( u = __make_link( bridge_ip, bridge_port, local_ip, up_port)) == NULL) {
d->close(d);
return NULL;
}
cc = calloc(1, sizeof *cc);
cc->_downlink = (struct udp_wrapper *)udp_readable_open(sizeof *cc->_downlink, d);
cc->_downlink->base.is_readable = __down_readable;
cc->_downlink->thiz = cc;
cc->_uplink = (struct udp_wrapper *)udp_readable_open(sizeof *cc->_uplink, u);
cc->_uplink->base.is_readable = __up_readable;
cc->_uplink->thiz = cc;
cc->_audio_up.thiz = cc;
cc->_audio_up.base.on_audio = __on_up_audio;
cc->_audio_down.thiz = cc;
cc->_audio_down.base.on_audio = __on_down_audio;
return cc;
}
void codec_free(codec_t *cc)
{
struct udp_wrapper *uw;
uw = cc->_downlink;
udp_readable_close(&uw->base);
uw = cc->_uplink;
udp_readable_close(&uw->base);
free(cc);
}

77
codec.h

@ -0,0 +1,77 @@
#ifndef __AUDIO_CODEC_H__
#define __AUDIO_CODEC_H__
#include <stdint.h>
#include "lan.h"
#include "wan.h"
#define AUDIO_ENC_ALL 0x00
#define AUDIO_ENC_10 0x01
#define AUDIO_ENC_712 0x02
#define AUDIO_ENC_PKT_LEN (666)
#define AUDIO_DEC_PKT_LEN (64)
struct AudioEncType {
uint8_t id1;
uint8_t id2;
uint8_t id3;
uint8_t id4;
uint16_t resv0;
uint8_t swId;
uint8_t fromId;
uint8_t toId;
uint8_t toSwId;
uint8_t origPosId;
uint8_t resv1;
uint8_t encType;
uint8_t contentId;
uint8_t flyType;
uint8_t flyId;
uint8_t payload[640];
uint32_t timeStamp;
uint32_t seqNum;
uint8_t checkNum;
uint8_t id5;
} __attribute__((packed));
struct AudioDecInType {
uint8_t id1;
uint8_t id2;
uint8_t id3;
uint8_t id4;
uint16_t resv0;
uint8_t swId;
uint8_t origSwId;
uint8_t toId;
uint8_t toSwId;
uint8_t origPosId;
uint8_t resv1;
uint8_t encType;
uint8_t contentId;
uint8_t flyType;
uint8_t flyId;
uint8_t payload[6];
uint8_t auxPayload[6];
uint8_t resv2[26];
uint32_t timeStamp;
uint32_t seqNum;
uint8_t checkNum;
uint8_t id5;
} __attribute((packed));
struct codec_complete {
void (*on_complete)(struct codec_complete *, uint8_t *buf, int len);
};
typedef struct codec codec_t;
codec_t *codec_new(const char *bridge_ip, int bridge_port, const char *local_ip, int down_port, int up_port);
void codec_set_up_complete(codec_t *cc, struct codec_complete *ccp);
void codec_set_enc_type(codec_t *cc, int type);
void codec_set_down_complete(codec_t *cc, struct codec_complete *ccp);
struct lan_audio_handler *codec_get_uplink_handler(codec_t *cc);
struct wan_audio_handler *codec_get_downlink_handler(codec_t *cc);
void codec_free(codec_t *cc);
#endif

28
CRC32.cpp → crc.c

@ -1,9 +1,10 @@
#include "CRC32.h" #include "crc.h"
static unsigned int crc_table[256];
/* /*
* crc表,32crc表 * crc表,32crc表
* crc表,, * crc表,,
* */ * */
void Crc32::init(void) void crc_begin(void)
{ {
unsigned int c; unsigned int c;
unsigned int i, j; unsigned int i, j;
@ -20,24 +21,15 @@ void Crc32::init(void)
} }
} }
uint32_t Crc32::doCrc(uint32_t crc,unsigned char *buffer, unsigned int size) unsigned int crc(void *_buffer, int size)
{ {
unsigned int i; int i;
unsigned int _crc = 0;
unsigned char *buffer = _buffer;
for (i = 0; i < size; i++) { for (i = 0; i < size; i++) {
crc = crc_table[(crc ^ buffer[i]) & 0xff] ^ (crc >> 8); _crc = crc_table[(_crc ^ buffer[i]) & 0xff] ^ (_crc >> 8);
} }
return crc ; return _crc ;
}
Crc32::Crc32()
{
init();
}
uint32_t Crc32::crc(uint8_t *buffer, int len)
{
uint32_t r = 0;
r = doCrc(r, buffer, len);
return r;
} }

7
crc.h

@ -0,0 +1,7 @@
#ifndef __CRC_H__
#define __CRC_H__
void crc_begin(void);
unsigned int crc(void *buf, int len);
#endif

239
lan.c

@ -0,0 +1,239 @@
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdbool.h>
#include "IdMapper.h"
#include "udp_readable.h"
#include "log.h"
#include "lan.h"
#include "codec.h"
#define LAN_PKT_MIN_LEN (16)
#define LAN_PKT_MAX_LEN (256)
struct decode_handler {
struct codec_complete base;
lan_t *thiz;
};
struct lan {
struct udp_readable base;
uint32_t seqnum;
struct decode_handler dec;
struct lanmsg_handler *_provider;
struct lan_audio_handler *_uplink;
};
struct codec_complete *lan_get_decode_handler(lan_t *ln)
{
return &ln->dec.base;
}
void lan_set_msghandler(lan_t *ln, struct lanmsg_handler *h)
{
ln->_provider = h;
}
void lan_set_uplink_handler(lan_t *ln, struct lan_audio_handler *h)
{
ln->_uplink = h;
}
static void __on_downlink(struct codec_complete *cc, uint8_t *buf, int len)
{
struct AudioEncType *aet;
struct MsgAudio *ma;
uint8_t msg[MSG_AUDIO_LEN] = {0};
struct decode_handler *dh = (struct decode_handler *)cc;
udp_t *u = dh->thiz->base.udp;
if (len < (int)(sizeof *aet)) {
log_printf("Audio too short.\n");
return;
}
ma = (struct MsgAudio *)(msg);
aet = (struct AudioEncType *)(buf);
ma->type = MSG_TYPE_AUDIO;
ma->recver = 0x19;
ma->sender = 0x07;
ma->swid = 0xB1;
ma->seqNum = htonl(++dh->thiz->seqnum);
ma->payloadLen = 160;
/*XXX: transcode aet->payload */
memcpy(ma->payload, aet->payload, ma->payloadLen);
u->send(u, msg, sizeof msg);
}
static void __do_audio(lan_t *ln, uint8_t *buf, int len)
{
struct MsgAudio *laph;
if (len < (int)(sizeof *laph))
return;
laph = (struct MsgAudio *)(buf);
laph->payloadLen = ntohl(laph->payloadLen);
if (len < (int)(sizeof *laph + laph->payloadLen)) {
log_printf("audio length too small, total: %d, payload: %d\n", len, laph->payloadLen);
return;
}
log_printf("recver< %d >: %x, sender: %x, mode: %d, recvChannel: %d, sendChannel: %d\n",
laph->payloadLen, laph->recver, laph->sender, laph->mode, laph->recvChannel, laph->sendChannel);
ln->_uplink->on_audio(ln->_uplink, laph);
}
static void __do_cmd(lan_t *ln, udp_t *u, uint8_t *buf, int len)
{
struct MsgCmd hdr, *sdp;
struct MsgTermStatus *mts;
uint8_t out;
uint16_t cmd;
sdp = (struct MsgCmd *)(buf);
hdr = *sdp;
cmd = ntohs(hdr.msgCmd);
log_printf("Lan cmd [%02x]\n", cmd);
switch (cmd) {
case MSG_CMD_HANDSHAKE:
hdr.sender = sdp->recver;
hdr.recver = sdp->sender;
hdr.msgCmd = htons(MSG_RES_HANDSHAKE);
#if 1
do {
uint8_t *dp;
dp = (uint8_t *)&hdr;
for (int x= 0; x < 12; ++x) {
log_printf("%02x ", dp[x]);
}
log_printf("\n");
} while (0);
#endif
u->send(u, &hdr, sizeof hdr);
len -= sizeof hdr;
buf += sizeof hdr;
/* 6 x 4 bytes:
* 0 1 2 3
* id downlink ptt alarm
*/
while (len > (int)sizeof (*mts)) {
mts = (struct MsgTermStatus *)buf;
out = getMappedWanId(mts->termId);
if (out > 0) {
ln->_provider->on_status(ln->_provider, out, mts->isAlarm);
}
len -= sizeof (*mts);
buf += sizeof (*mts);
}
break;
case MSG_CMD_PTTON:
out = getMappedWanId(hdr.sender);
if (out > 0) {
ln->_provider->on_ptt(ln->_provider, ln, &hdr, out, true);
}
break;
case MSG_CMD_PTTOFF:
out = getMappedWanId(hdr.sender);
if (out > 0) {
ln->_provider->on_ptt(ln->_provider, ln, &hdr, out, false);
}
break;
}
}
static void __is_readable(udp_readable_t *ur)
{
uint8_t buf[LAN_PKT_MAX_LEN] = {0};
int len;
udp_t *_u = ur->udp;
log_printf("lan reading\n");
if ((len = _u->recv(_u, buf, sizeof buf)) < LAN_PKT_MIN_LEN) {
return;
}
#if 1
do {
log_printf("Lan: %d bytes\n", len);
for (int x = 0; x < len; ++x) {
log_printf("%02x%c", buf[x], ((x + 1) % 16) ? ' ' : '\n');
}
log_printf("\n");
} while (0);
#endif
switch (buf[0]) {
case MSG_TYPE_CMD:
__do_cmd((lan_t *)(ur), _u, buf, len);
break;
case MSG_TYPE_AUDIO:
__do_audio((lan_t *)ur, buf, len);
break;
case MSG_TYPE_ALARM:
break;
}
}
int lan_ptt_response(lan_t *ln, int resp_type, struct MsgCmd *hdr, int status)
{
struct MsgCmd pkt;
udp_t *u = ln->base.udp;
pkt = *hdr;
pkt.recver = hdr->sender;
pkt.sender = hdr->recver;
switch (resp_type) {
case RESP_PTT_ON:
if (status == RESP_PTT_OK) {
pkt.msgCmd = htons(MSG_RES_PTTON);
} else {
pkt.msgCmd = htons(MSG_REFUSE_PTTON);
}
break;
case RESP_PTT_OFF:
pkt.msgCmd = htons(MSG_RES_PTTOFF);
break;
}
u->send(u, &pkt, sizeof pkt);
return 0;
}
lan_t *lan_new(const char *dest_addr, int port, const char *local_if)
{
udp_t *u;
lan_t *ln;
if ((u = udp_open()) == NULL) {
log_printf("'%s[%d]: can't create Lan socket\n", __func__, __LINE__);
return NULL;
}
log_printf("local: %s, %s, %d\n", local_if, dest_addr, port);
if (u->bind(u, local_if, port) < 0) {
log_printf("'%s[%d]: can't bind Lan socket\n", __func__, __LINE__);
u->close(u);
return NULL;
}
if (u->connect(u, dest_addr, port) < 0) {
log_printf("'%s[%d]: can't connect Lan socket\n", __func__, __LINE__);
u->close(u);
return NULL;
}
ln = (lan_t *)udp_readable_open(sizeof *ln, u);
if (ln == NULL) {
u->close(u);
return NULL;
}
ln->base.is_readable = __is_readable;
ln->seqnum = 0;
ln->dec.thiz = ln;
ln->dec.base.on_complete = __on_downlink;
return ln;
}
void lan_free(lan_t *ln)
{
udp_readable_close(&ln->base);
}

117
lan.h

@ -0,0 +1,117 @@
#ifndef __LAN_H__
#define __LAN_H__
#include <stdint.h>
#define NOOFTERMS 6
#define MSG_TYPE_CMD 0x79
#define MSG_TYPE_AUDIO 0x7A
#define MSG_TYPE_ALARM 0x7C
#define MSG_CMD_HANDSHAKE 0x0003
#define MSG_RES_HANDSHAKE 0x0002
#define MSG_CMD_PTTON 0x0007
#define MSG_RES_PTTON 0x0006
#define MSG_REFUSE_PTTON 0x0005
#define MSG_CMD_PTTOFF 0x000A
#define MSG_RES_PTTOFF 0x000B
struct MsgCmd {
uint8_t type;
uint8_t recver;
uint8_t sender;
uint8_t swid;
uint16_t msgCmd;
uint8_t termId;
uint8_t channel;
uint32_t seqNum;
} __attribute__((packed));
struct MsgTermStatus {
uint8_t termId;
uint8_t isDowning;
uint8_t isPtt;;
uint8_t isAlarm;
} __attribute__((packed));
#define MSG_AUDIO_LEN (166)
struct MsgAudio {
uint8_t type;
uint8_t recver;
uint8_t sender;
uint8_t swid;
uint8_t reserv;
uint8_t mode;
uint8_t recvChannel;
uint8_t sendChannel;
uint32_t seqNum;
uint32_t payloadLen;
uint8_t payload[0];
} __attribute__((packed));
struct MsgAlarm {
uint8_t type;
uint8_t recver;
uint8_t sender;
uint8_t swid;
uint16_t reserv;
uint8_t alarmPos;
uint8_t alarmTerm;
uint32_t seqNum;
} __attribute__((packed));
#define RESP_PTT_OK 0x01
#define RESP_PTT_FAILED 0x02
typedef struct lan lan_t;
struct lan_audio_handler {
void (*on_audio)(struct lan_audio_handler *, struct MsgAudio *);
};
struct lanmsg_handler {
void (*on_ptt)(struct lanmsg_handler *, lan_t *, struct MsgCmd *hdr, uint8_t posId, int on);
void (*on_status)(struct lanmsg_handler *, uint8_t id, uint8_t status);
};
enum {RESP_PTT_ON, RESP_PTT_OFF};
lan_t *lan_new(const char *dest_addr, int port, const char *local_if);
struct codec_complete *lan_get_decode_handler(lan_t *ln);
void lan_set_msghandler(lan_t *, struct lanmsg_handler *);
void lan_set_uplink_handler(lan_t *, struct lan_audio_handler *);
int lan_ptt_response(lan_t *ln, int resp_type, struct MsgCmd *hdr, int status);
void lan_free(lan_t *);
#if 0
class Lan : public AudioCompleteProvider , public UdpReadable {
private:
PTTProvider *_provider;
AudioUpProvider *_audioUp;
uint32_t _myseq;
void doCmd(uint8_t *buf, int len);
void doAudio(uint8_t *buf, int len);
public:
enum {RESP_PTT_ON, RESP_PTT_OFF};
Lan() : _provider(0), _myseq(0) {}
int begin(const char *group_addr, int port, const char *local_if);
virtual void isReadable(Udp &udp);
inline int send(const void *buf, int len) {
return _udp.send(buf, len);
}
int onResponse(int resp_type, struct MsgCmd *hdr, int status);
void setPTTProvider(PTTProvider *_p) {_provider = _p;}
void setAudioUpProvider(AudioUpProvider *_p) {_audioUp = _p;}
/* down complete, multiast to lan */
virtual void onComplete(uint8_t *buf, int len);
};
#endif
#endif

12
Log.cpp → log.c

@ -1,9 +1,9 @@
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
#include "Log.h" #include "log.h"
int Log::printf(const char *fmt, ...) int log_printf(const char *fmt, ...)
{ {
va_list ap; va_list ap;
int n; int n;
@ -14,13 +14,13 @@ int Log::printf(const char *fmt, ...)
return (n); return (n);
} }
void Log::begin() int log_begin()
{ {
return 0;
} }
void Log::end() int log_end()
{ {
return 0;
} }
class Log Log;

7
log.h

@ -0,0 +1,7 @@
#ifndef __NEWC_LOG_H__
#define __NEWC_LOG_H__
int log_begin(void);
int log_end(void);
int log_printf(const char *fmt,...);
#endif

10
main.c

@ -0,0 +1,10 @@
#include "runtime.h"
int main(int argc, char *argv[])
{
runtime_init();
runtime_parse_args(argc, argv);
runtime_begin();
return runtime_loop();
}

15
main.cpp

@ -1,15 +0,0 @@
#include "Runtime.h"
#include "Timer.h"
int main(int argc, char *argv[])
{
Runtime.parseArgs(argc, argv);
Runtime.begin();
if (0) {
Timer tm;
tm.begin();
tm.active(1000);
}
return Runtime.loop();
}

10
makefile

@ -7,9 +7,9 @@ LIBDIR := $(TARGET_ROOT)/lib
#DEBUG := -g -ggdb #DEBUG := -g -ggdb
DEBUG := -O2 -s DEBUG := -O2 -s
CFLAGS += -D_GNU_SOURCE -I$(PWD) -I$(PWD)/class -I$(INCLUDE) -I$(INCLUDE)/luajit-2.0 -Wall -Wextra $(DEBUG) CFLAGS += -std=gnu99 -D_GNU_SOURCE -fno-strict-aliasing \
-I$(PWD) -I$(PWD)/class -I$(INCLUDE) -I$(INCLUDE)/luajit-2.0 -Wall -Wextra \
CXXFLAGS += $(CFLAGS) $(DEBUG)
LIBEVENT := -levent -levent_core -levent_extra -levent_pthreads LIBEVENT := -levent -levent_core -levent_extra -levent_pthreads
LIBSNDFILE := LIBSNDFILE :=
@ -18,13 +18,13 @@ LDFLAGS += -L$(TARGET_ROOT)/lib -Wl,--start-group,-Bstatic $(LIBEVENT) $(LIBSNDF
#CLASS_OBJS := class/buffer.o class/event.o class/udp.o #CLASS_OBJS := class/buffer.o class/event.o class/udp.o
OBJS := $(CLASS_OBJS) CRC32.o Udp.o UdpEvent.o UdpReadable.o Log.o Lan.o Wan.o AudioBridge.o CharConv.o Runtime.o Timer.o IdMapper.o main.o OBJS := $(CLASS_OBJS) crc.o udp.o udp_readable.o log.o timer.o lan.o wan.o codec.o char_conv.o runtime.o IdMapper.o main.o
comile: zkb comile: zkb
@echo "compile done" @echo "compile done"
zkb: $(OBJS) zkb: $(OBJS)
$(CC) -o $@ $^ $(LDFLAGS) -lstdc++ $(CC) -o $@ $^ $(LDFLAGS)
clean: clean:
rm -rf $(OBJS) rm -rf $(OBJS)

174
runtime.c

@ -0,0 +1,174 @@
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include "runtime.h"
#include "log.h"
#include "udp.h"
#include "lan.h"
#include "wan.h"
#include "codec.h"
#include "crc.h"
#define LAN_IF "eth0"
#define LAN_FROM "192.168.9.25"
#define LAN_PORT 5600
#define BGE_IP "192.168.9.19"
#define BGE_PORT 6419
#define BGE_UP_PORT 6402
#define BGE_DOWN_PORT 6400
/*
* Please disable rp_filter
* edit /etc/sysctl.conf
*
* net.ipv4.conf.default.rp_filter = 0
* net.ipv4.conf.all.rp_filter = 0
*
* add route for eth1
* route add -net 192.168.31.0/24 dev eth1
*/
#if 1
#define WAN_IF "eth1"
#define WAN_GROUP "225.0.0.5"
#define WAN_GROUP_PORT 8300
#define WAN_STATUS_PORT 8100
#else
#define WAN_IF "eth0"
#define WAN_GROUP "224.0.0.24"
#define WAN_GROUP_PORT 8300
#define WAN_STATUS_PORT 5100
#endif
struct runtime Runtime;
void runtime_init()
{
struct event_config *config;
Runtime._lan_if = (char *)LAN_IF;
Runtime._lan_grp_addr = (char *)LAN_FROM;
Runtime._lan_grp_port = LAN_PORT;
Runtime._bge_ip = (char *)BGE_IP;
Runtime._bge_port = BGE_PORT;
Runtime._up_port = BGE_UP_PORT;
Runtime._down_port = BGE_DOWN_PORT;
Runtime._wan_if = (char *)WAN_IF;
Runtime._wan_grp_addr = (char *)WAN_GROUP;
Runtime._wan_grp_port = WAN_GROUP_PORT;
Runtime._wan_status_port = WAN_STATUS_PORT;
config = event_config_new();
event_config_avoid_method(config, "select");
event_config_require_features(config, EV_FEATURE_ET);
Runtime.evbase = event_base_new_with_config(config);
event_config_free(config);
log_begin();
crc_begin();
}
static void print_help()
{
log_printf("usage: cmd [option], options as:\n\t"
"--lanif, -l: set lan ethx interface, eg: \"ethx\"\n\t"
"--landest, -g: set lan multicast address, eg: \"192.168.9.25\"\n\t"
"--lanport, -p: set lan multicast port, eg: 5600\n\t"
"--wanif, -w: set lan ethx interface, eg: \"ethx\"\n\t"
"--wangrp, -r: set lan multicast address, eg: \"255.0.0.5\"\n\t"
"--wanport, -t: set lan multicast port, eg: 5600\n\t"
"--help, -h: print this message.\n");
}
void runtime_parse_args(int argc, char *argv[])
{
int c;
static struct option options[] = {
{"lanif", required_argument, NULL, 'l'},
{"landest", required_argument, NULL, 'g'},
{"lanport", required_argument, NULL, 'p'},
{"wanif", required_argument, NULL, 'w'},
{"wangrp", required_argument, NULL, 'r'},
{"wanport", required_argument, NULL, 't'},
{"wanstport", required_argument, NULL, 'o'},
{"help", no_argument, NULL, 'h'},
{NULL, 0, NULL, 0}
};
while ((c = getopt_long(argc, argv, "l:g:p:w:r:t:o:h", options, NULL)) != -1) {
switch (c) {
case 'l':
Runtime._lan_if = optarg;
break;
case 'g':
Runtime._lan_grp_addr = optarg;
break;
case 'p':
Runtime._lan_grp_port = atoi(optarg);
break;
case 'w':
Runtime._wan_if = optarg;
break;
case 'r':
Runtime._wan_grp_addr = optarg;
case 't':
Runtime._wan_grp_port = atoi(optarg);
break;
case 'o':
Runtime._wan_status_port = atoi(optarg);
break;
case 'h':
print_help();
exit(0);
}
}
}
void runtime_begin(void)
{
char local_if[64] = {0};
char wan_if[64] = {0};
getip(Runtime._lan_if, local_if, sizeof local_if);
if ((Runtime._lan = lan_new(Runtime._lan_grp_addr, Runtime._lan_grp_port, local_if)) == NULL) {
log_printf("lan initialize failed.\n");
exit(-1);
}
if ((Runtime._abge = codec_new(Runtime._bge_ip, Runtime._bge_port, local_if, Runtime._down_port, Runtime._up_port)) == NULL) {
log_printf("audio bridge initialize failed.\n");
exit(-2);
}
getip(Runtime._wan_if, wan_if, sizeof wan_if);
if ((Runtime._wan = wan_new(Runtime._wan_grp_addr, Runtime._wan_grp_port, wan_if, Runtime._wan_status_port)) == NULL) {
log_printf("wan initialize failed.\n");
exit(-3);
}
if ((Runtime._cv = char_conv_new(6801, 6802)) == NULL) {
log_printf("char convter initiazlie failed.\n");
exit(-4);
}
#if 0
static AlarmTimer at(&_conv);
at.begin();
at.active(1000);
#endif
codec_set_down_complete(Runtime._abge, lan_get_decode_handler(Runtime._lan));
codec_set_up_complete(Runtime._abge, wan_get_encode_handler(Runtime._wan));
lan_set_uplink_handler(Runtime._lan, codec_get_uplink_handler(Runtime._abge));
wan_set_downlink_handler(Runtime._wan, codec_get_downlink_handler(Runtime._abge));
lan_set_msghandler(Runtime._lan, wan_get_msghandler(Runtime._wan));
wan_set_alarm_handler(Runtime._wan, char_conv_get_alarm_handler(Runtime._cv));
}
int runtime_loop()
{
return event_base_dispatch(Runtime.evbase);
}

43
runtime.h

@ -0,0 +1,43 @@
#ifndef __RUNTIME_H__
#define __RUNTIME_H__
#include <event2/event.h>
#include "lan.h"
#include "wan.h"
#include "codec.h"
#include "char_conv.h"
struct runtime {
struct event_base *evbase;
/* lan config */
lan_t *_lan;
char *_lan_if;
char *_lan_grp_addr;
int _lan_grp_port;
/* audio bridge */
codec_t * _abge;
char *_bge_ip;
int _bge_port;
int _up_port;
int _down_port;
/* Wan */
wan_t *_wan;
char *_wan_if;
char *_wan_grp_addr;
int _wan_grp_port;
int _wan_status_port;
/* char conv */
char_conv_t *_cv;
};
extern struct runtime Runtime;
void runtime_parse_args(int argc, char *argv[]);
void runtime_init(void);
void runtime_begin(void);
int runtime_loop(void);
#endif

45
timer.c

@ -0,0 +1,45 @@
#include <stdlib.h>
#include "timer.h"
#include "log.h"
#include "runtime.h"
static void __helper(int fd, short what, void *arg)
{
struct timer *t = arg;
(void)fd;
(void)what;
t->on_timer(t);
}
struct timer *timer_new(size_t alloc)
{
struct timer *t;
if (alloc < sizeof *t)
return NULL;
t = calloc(1, alloc);
event_assign(&t->_evt, Runtime.evbase, -1, EV_TIMEOUT | EV_PERSIST, __helper, t);
return t;
}
void timer_active(struct timer * t, int ms)
{
struct timeval tv;
tv.tv_sec = ms / 1000;
tv.tv_usec = ms % 1000;
event_add(&t->_evt, &tv);
}
void timer_deactive(struct timer *t)
{
event_del(&t->_evt);
}
void timer_free(struct timer *t)
{
free(t);
}

17
timer.h

@ -0,0 +1,17 @@
#ifndef __ETIMER_H__
#define __ETIMER_H__
#include <event2/event.h>
#include <event2/event_struct.h>
struct timer {
struct event _evt;
void (*on_timer)(struct timer *);
};
struct timer *timer_new(size_t alloc);
void timer_active(struct timer *, int ms);
void timer_deactive(struct timer *);
void timer_free(struct timer *);
#endif

144
Udp.cpp → udp.c

@ -1,21 +1,25 @@
#include <unistd.h> #include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <errno.h> #include <errno.h>
#include <fcntl.h> #include <fcntl.h>
#include <string.h> #include <string.h>
#include <netinet/in.h>
#include <netinet/in.h>
#include <net/if.h>
#include <arpa/inet.h>
#include <event2/util.h> #include <event2/util.h>
#include "Udp.h" #include "udp.h"
#include "Log.h" #include "log.h"
Udp::Udp() struct udp_multicast {
:sock(-1), isMcast(false) struct udp base;
{ struct sockaddr_in dest_addr;
memset(&destAddr, 0, sizeof destAddr); };
}
int Udp::bind(const char *addr, int p) static int __bind(udp_t *s, const char *addr, int p)
{ {
struct sockaddr_in local_addr; struct sockaddr_in local_addr;
@ -24,69 +28,74 @@ int Udp::bind(const char *addr, int p)
local_addr.sin_port = htons(p); local_addr.sin_port = htons(p);
local_addr.sin_addr.s_addr = addr ? inet_addr(addr) : INADDR_ANY; local_addr.sin_addr.s_addr = addr ? inet_addr(addr) : INADDR_ANY;
return ::bind(sock, (struct sockaddr *)&local_addr, sizeof local_addr); return bind(s->sock, (struct sockaddr *)&local_addr, sizeof local_addr);
} }
int Udp::open() static int __close(udp_t *s)
{ {
sock = socket(AF_INET, SOCK_DGRAM, 0); int n;
if (sock >= 0) { n = close(s->sock);
evutil_make_socket_nonblocking(sock); free(s);
int reuse = 1; return n;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse);
setsockopt(sock, SOL_SOCKET, SO_REUSEPORT, &reuse, sizeof reuse);
isMcast = false;
return 0;
}
return -1;
} }
int Udp::close() static int __connect(udp_t *s, const char *to, int p)
{ {
int s; struct sockaddr_in sin;
memset(&sin, 0, sizeof sin);
sin.sin_family = AF_INET;
sin.sin_port = htons(p);
sin.sin_addr.s_addr = inet_addr(to);
s = ::close(sock); return connect(s->sock, (struct sockaddr *)&sin, sizeof sin);
sock = -1;
return s;
} }
int Udp::send(const void *buf, int len) static int __send(udp_t *s, void *buf, int len)
{ {
if (isMcast) { return write(s->sock, buf, len);
return sendto(sock, buf, len, 0, (struct sockaddr *)&destAddr,
sizeof destAddr);
} else {
return write(sock, buf, len);
}
} }
int Udp::recv(void *buf, int len) static int __recv(udp_t *s, void *buf, int len)
{ {
return read(sock, buf, len); return read(s->sock, buf, len);
} }
int Udp::connect(const char *to, int p) static int __send2(udp_t *s, void *buf, int len)
{ {
struct sockaddr_in sin; struct udp_multicast *_s = (struct udp_multicast *)(s);
return sendto(_s->base.sock, buf, len, 0, (struct sockaddr *)&_s->dest_addr,
memset(&sin, 0, sizeof sin); sizeof _s->dest_addr);
sin.sin_family = AF_INET; }
sin.sin_port = htons(p);
sin.sin_addr.s_addr = inet_addr(to);
return ::connect(sock, (struct sockaddr *)&sin, sizeof sin); udp_t *udp_open()
{
int s;
udp_t *u;
if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
return NULL;
u = calloc(1, sizeof *u);
u->sock = s;
u->bind = __bind;
u->connect = __connect;
u->send = __send;
u->recv = __recv;
u->close = __close;
return u;
} }
int Udp::openMulticast(const char *grp_addr, int port, const char *local) udp_t * udp_open_mcast(const char *grp_addr, int port, const char *local)
{ {
struct sockaddr_in local_addr; struct sockaddr_in local_addr;
struct ip_mreq group; struct ip_mreq group;
struct in_addr ethx; struct in_addr ethx;
int sm = -1; int sock;
struct udp_multicast *u;
sock = socket(AF_INET, SOCK_DGRAM, 0); sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0) { if (sock < 0) {
goto done; return NULL;
} }
evutil_make_socket_nonblocking(sock); evutil_make_socket_nonblocking(sock);
@ -100,26 +109,26 @@ int Udp::openMulticast(const char *grp_addr, int port, const char *local)
local_addr.sin_family = AF_INET; local_addr.sin_family = AF_INET;
local_addr.sin_port = htons(port); local_addr.sin_port = htons(port);
local_addr.sin_addr.s_addr = INADDR_ANY; local_addr.sin_addr.s_addr = INADDR_ANY;
if(::bind(sock, (struct sockaddr*)&local_addr, sizeof(local_addr))){ if(bind(sock, (struct sockaddr*)&local_addr, sizeof(local_addr))){
Log.printf("%s[%d]: bind %d (%s)\n", __func__, __LINE__, errno, strerror(errno)); log_printf("%s[%d]: bind %d (%s)\n", __func__, __LINE__, errno, strerror(errno));
::close(sock); close(sock);
goto done; return NULL;
} }
ethx.s_addr = inet_addr(local); ethx.s_addr = inet_addr(local);
if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &ethx, sizeof (ethx)) < 0) { if (setsockopt(sock, IPPROTO_IP, IP_MULTICAST_IF, &ethx, sizeof (ethx)) < 0) {
Log.printf("%s[%d]: setsockopt %d (%s)\n", __func__, __LINE__, errno, strerror(errno)); log_printf("%s[%d]: setsockopt %d (%s)\n", __func__, __LINE__, errno, strerror(errno));
::close(sock); close(sock);
goto done; return NULL;
} }
group.imr_multiaddr.s_addr = inet_addr(grp_addr); group.imr_multiaddr.s_addr = inet_addr(grp_addr);
group.imr_interface.s_addr = inet_addr(local); group.imr_interface.s_addr = inet_addr(local);
if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0){ if(setsockopt(sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0){
Log.printf("%s[%d]: setsockopt %d (%s)\n", __func__, __LINE__, errno, strerror(errno)); log_printf("%s[%d]: setsockopt %d (%s)\n", __func__, __LINE__, errno, strerror(errno));
::close(sock); close(sock);
goto done; return NULL;
} }
/* don't lookback */ /* don't lookback */
@ -128,26 +137,29 @@ int Udp::openMulticast(const char *grp_addr, int port, const char *local)
setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof loop); setsockopt(sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof loop);
} while (0); } while (0);
memset(&destAddr, 0, sizeof destAddr); u = calloc(1, sizeof *u);
destAddr.sin_family = AF_INET; u->base.sock = sock;
destAddr.sin_port = htons(port); u->base.bind = __bind;
destAddr.sin_addr.s_addr = inet_addr(grp_addr); u->base.connect = __connect;
isMcast = true; u->base.send = __send2;
u->base.recv = __recv;
u->base.close = __close;
sm = 0; u->dest_addr.sin_family = AF_INET;
done: u->dest_addr.sin_port = htons(port);
return sm; u->dest_addr.sin_addr.s_addr = inet_addr(grp_addr);
return &u->base;
} }
int Udp::getip(const char *ethx, char *addr, int len) int getip(const char *ethx, char *addr, int len)
{ {
int ln, fd; int ln, fd;
struct ifreq ifr; struct ifreq ifr;
int ret = 0; int ret = 0;
char *p; char *p;
fd = ::socket(AF_INET, SOCK_DGRAM, 0); fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd < 0) { if (fd < 0) {
return -1; return -1;
} }
@ -169,7 +181,7 @@ int Udp::getip(const char *ethx, char *addr, int len)
ret = -1; ret = -1;
} }
} }
::close(fd); close(fd);
return ret; return ret;
} }

18
udp.h

@ -0,0 +1,18 @@
#ifndef __UDP_NEWC_H__
#define __UDP_NEWC_H__
typedef struct udp udp_t;
struct udp {
int sock;
int (*bind)(udp_t *, const char *local_ip, int local_port);
int (*connect)(udp_t *, const char *remote_ip, int remote_port);
int (*send)(udp_t *, void *buf, int len);
int (*recv)(udp_t *, void *buf, int len);
int (*close)(udp_t *);
};
udp_t *udp_open(void);
udp_t *udp_open_mcast(const char *group, int port, const char *local_if);
int getip(const char *ethx, char *addr, int len);
#endif

33
udp_readable.c

@ -0,0 +1,33 @@
#include <stdlib.h>
#include "udp_readable.h"
#include "runtime.h"
static void __helper(int fd , short what, void *arg)
{
udp_readable_t *ur = arg;
(void)fd;
if (what & EV_READ) {
ur->is_readable(ur);
}
}
udp_readable_t *udp_readable_open(size_t alloc_size, udp_t *u)
{
udp_readable_t *ur;
if (alloc_size < sizeof *ur)
return NULL;
ur = calloc(1, alloc_size);
ur->udp = u;
event_assign(&ur->evt, Runtime.evbase, u->sock, EV_READ | EV_PERSIST, __helper, ur);
event_add(&ur->evt, NULL);
return ur;
}
void udp_readable_close(udp_readable_t *ur)
{
event_del(&ur->evt);
ur->udp->close(ur->udp);
free(ur);
}

17
udp_readable.h

@ -0,0 +1,17 @@
#ifndef __UDP_READABLE_H__
#define __UDP_READABLE_H__
#include <event2/event.h>
#include <event2/event_struct.h>
#include "udp.h"
typedef struct udp_readable udp_readable_t;
struct udp_readable {
struct event evt;
udp_t *udp;
void (*is_readable)(udp_readable_t *);
};
udp_readable_t *udp_readable_open(size_t alloc_size, udp_t *u);
void udp_readable_close(udp_readable_t *);
#endif

181
wan.c

@ -0,0 +1,181 @@
#include <time.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include "udp_readable.h"
#include "log.h"
#include "codec.h"
#include "wan.h"
#include "lan.h"
struct encode_handler {
struct codec_complete base;
wan_t *thiz;
};
struct wanmsg_handler {
struct lanmsg_handler base;
wan_t *thiz;
};
struct wan {
struct udp_readable base;
struct encode_handler enc;
struct wanmsg_handler msghdr;
udp_t *stsock;
struct wan_audio_handler *_downlink;
struct wan_alarm_handler *_alarm;
struct WanStatusType _stBuf;
uint32_t _stSeq;
};
struct lanmsg_handler *wan_get_msghandler(wan_t *wn)
{
return &wn->msghdr.base;
}
void wan_set_downlink_handler(wan_t *wn, struct wan_audio_handler *h)
{
wn->_downlink = h;
}
void wan_set_alarm_handler(wan_t *wan, struct wan_alarm_handler *h)
{
wan->_alarm = h;
}
struct codec_complete *wan_get_encode_handler(wan_t *wn)
{
return &wn->enc.base;
}
static void __is_readable(udp_readable_t *ur)
{
uint8_t data[1500] = {0};
int len;
wan_t *wn = (wan_t *)ur;
udp_t *u = ur->udp;
if ((len = u->recv(u, data, sizeof data)) <= 0)
return;
#if 0
Log.printf("Wan recv: %d bytes\n", len);
for (int i = 0; i < len; ++i) {
Log.printf("%02x%c", data[i], ((i + 1) % 16) ? ' ' : '\n');
}
Log.printf("\n");
#endif
if ((data[0] == 0xAA) && (data[1] == 0x55)) {
if ((len == 32) && (data[6] == 0x91)) {
struct WanAudioType *wat = (struct WanAudioType *)data;
wn->_downlink->on_audio(wn->_downlink, wat);
}
}
/*XXX: if alarming , call _alarm->onAlarm() */
if ((data[0] == 0xAC) && (data[1] == 0x93)) {
if ((len == 64) && (data[13] == 0xF0)) {
struct WanAlarmType *wmt = (struct WanAlarmType *)data;
wn->_alarm->on_alarm(wn->_alarm, wmt);
}
}
}
static void __on_uplink(struct codec_complete *cc, uint8_t *buf, int len)
{
struct encode_handler *eh = (struct encode_handler *)cc;
udp_t *u = eh->thiz->base.udp;
u->send(u, buf, len);
}
static void __on_ptt(struct lanmsg_handler *lh, lan_t *ln, struct MsgCmd *hdr, uint8_t posId, int on)
{
struct wanmsg_handler *wh = (struct wanmsg_handler *)lh;
wan_t *wn = wh->thiz;
if (on) {
} else {
}
lan_ptt_response(ln, on ? RESP_PTT_ON : RESP_PTT_OFF, hdr, RESP_PTT_OK);
}
static void __on_status(struct lanmsg_handler *lh, uint8_t id, uint8_t status)
{
struct wanmsg_handler *wh = (struct wanmsg_handler *)lh;
int len = 0;
uint8_t *sbuf;
wan_t *wn = wh->thiz;
wn->_stBuf.destId = status ? id : 0;
/*
* 0: don't start
* 1: playing
* 2: idle
*/
wn->_stBuf.status = status ? 0x01 : 0x02;
wn->_stBuf.time = htonl(time(NULL));
wn->_stBuf.seq = htonl(++wn->_stSeq);
uint32_t cs = 0;
len = sizeof wn->_stBuf - 2;
sbuf = (uint8_t *)&wn->_stBuf;
for (int x = 0; x < len; ++x) {
cs += sbuf[x];
}
wn->_stBuf.checkNum = cs & 0xff;
len = wn->stsock->send(wn->stsock, &wn->_stBuf, sizeof wn->_stBuf);
if (len < 0) {
log_printf("%s:%d errno (%d) %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
// Log.printf("status sending %d bytes\n", len);
}
wan_t* wan_new(const char *group_addr, int port, const char *wlan_if, int stport)
{
wan_t *wn;
udp_t *udp, *sts;
log_printf("Wan group: %s, port: %d, wan: %s\n", group_addr, port, wlan_if);
if ((udp = udp_open_mcast(group_addr, port, wlan_if)) == NULL) {
log_printf("'%s[%d]: can't create multicast socket\n", __FILE__, __LINE__);
return NULL;
}
if ((sts = udp_open_mcast(group_addr, stport, wlan_if)) == NULL) {
log_printf("'%s[%d]: can't create status multicast socket\n", __FILE__, __LINE__);
udp->close(udp);
return NULL;
}
wn = (wan_t *)udp_readable_open(sizeof *wn, udp);
wn->stsock = sts;
wn->_stSeq = 0;
wn->enc.thiz = wn;
wn->enc.base.on_complete = __on_uplink;
wn->base.is_readable = __is_readable;
wn->msghdr.thiz = wn;
wn->msghdr.base.on_ptt = __on_ptt;
wn->msghdr.base.on_status = __on_status;
memset(&wn->_stBuf, 0, sizeof wn->_stBuf);
wn->_stBuf.id1 = 0xAC;
wn->_stBuf.id2 = 0x93;
wn->_stBuf.id3 = 0x27;
wn->_stBuf.id4 = 0x21;
wn->_stBuf.srcPosId = 0xB1;
wn->_stBuf.srcSwId = 0xD8;
wn->_stBuf.destSwId = 0xE8;
wn->_stBuf.initPosId = 0xB1;
wn->_stBuf.contentId = 0xF3;
wn->_stBuf.id5 = 0x14;
return wn;
}
void wan_free(wan_t *wn)
{
wn->stsock->close(wn->stsock);
udp_readable_close(&wn->base);
}

43
Wan.h → wan.h

@ -1,12 +1,7 @@
#ifndef __WAN_H__ #ifndef __WAN_H__
#define __WAN_H__ #define __WAN_H__
#include "PTTProvider.h" #include "lan.h"
#include "AudioProvider.h"
#include "AlarmProvider.h"
#include "UdpReadable.h"
class Lan;
struct WanAudioType { struct WanAudioType {
uint8_t hdr0; uint8_t hdr0;
@ -67,32 +62,22 @@ struct WanStatusType {
uint8_t id5; uint8_t id5;
} __attribute__((packed)); } __attribute__((packed));
class Wan : public PTTProvider, public AudioCompleteProvider, public UdpReadable { struct wan_audio_handler {
private: void (*on_audio)(struct wan_audio_handler *self, struct WanAudioType *);
AudioDownProvider *_audioDown; };
AlarmProvider *_alarm;
Udp _stSock;
struct WanStatusType _stBuf;
uint32_t _stSeq;
public:
int begin(const char *group_addr, int port, const char *wlan_if, int stPort);
void setAudioDownProvider(AudioDownProvider *_p) { _audioDown = _p;}
void setAlarmProvider(AlarmProvider *_p) { _alarm = _p;}
/* on recv */
virtual void isReadable(Udp &);
/* PTT */ struct wan_alarm_handler {
virtual void onPTT(Lan *, struct MsgCmd *hdr, uint8_t posId, bool on); void (*on_alarm)(struct wan_alarm_handler *self, struct WanAlarmType *);
};
/* status: 0 -> suspend , 1 -> alarming, 2 -> idle*/ typedef struct wan wan_t;
virtual void onStatus(uint8_t id, uint8_t status);
/* uplink data */ wan_t* wan_new(const char *group_addr, int port, const char *wlan_if, int stport);
virtual void onComplete(uint8_t *buf, int len); void wan_free(wan_t *wn);
}; void wan_set_alarm_handler(wan_t *wan, struct wan_alarm_handler *h);
void wan_set_downlink_handler(wan_t *, struct wan_audio_handler *);
struct codec_complete *wan_get_encode_handler(wan_t *wn);
struct lanmsg_handler *wan_get_msghandler(wan_t *wn);
#endif #endif
Loading…
Cancel
Save