surenyi
9 years ago
44 changed files with 1475 additions and 1340 deletions
@ -1,10 +0,0 @@ |
|||||
#ifndef __ALARM_PROVIDER_H__ |
|
||||
#define __ALARM_PROVIDER_H__ |
|
||||
|
|
||||
class AlarmProvider { |
|
||||
public: |
|
||||
void onAlarm(const char *str, int len); |
|
||||
}; |
|
||||
|
|
||||
#endif |
|
||||
|
|
@ -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); |
|
||||
} |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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(); |
|
||||
} |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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; |
|
||||
} |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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; |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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); |
|
||||
} |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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; |
|
||||
} |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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); |
|
||||
} |
|
||||
|
|
@ -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 |
|
||||
|
|
@ -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);
|
|
||||
} |
|
||||
|
|
@ -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); |
||||
|
} |
||||
|
|
@ -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 |
||||
|
|
@ -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); |
||||
|
} |
||||
|
|
@ -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 |
||||
|
|
@ -0,0 +1,7 @@ |
|||||
|
#ifndef __CRC_H__ |
||||
|
#define __CRC_H__ |
||||
|
|
||||
|
void crc_begin(void); |
||||
|
unsigned int crc(void *buf, int len); |
||||
|
#endif |
||||
|
|
@ -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); |
||||
|
} |
||||
|
|
@ -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 |
||||
|
|
@ -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 |
||||
|
|
@ -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(); |
||||
|
} |
||||
|
|
@ -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(); |
|
||||
} |
|
||||
|
|
@ -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); |
||||
|
} |
||||
|
|
@ -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 |
||||
|
|
@ -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); |
||||
|
} |
||||
|
|
@ -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 |
||||
|
|
@ -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 |
||||
|
|
@ -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); |
||||
|
} |
||||
|
|
@ -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 |
||||
|
|
@ -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); |
||||
|
} |
||||
|
|
Loading…
Reference in new issue