📄 connect.c
字号:
osb = &ebuf;
/* DES encryption. */
if (d->deskey[0]) {
if (protocolSent == PROTOCOL_RTP || protocolSent == PROTOCOL_VAT) {
LONG vlen = pktlen;
des_key_schedule sched;
des_cblock ivec;
/* If we're DES encrypting we must round the size of
the data to be sent to be a multiple of 8 so that
the entire DES frame is sent. If this is an RTP
packet, we may have to set the Pad bit in the
header and include a count of pad bytes at the end
of the packet. */
_fmemset(ivec, 0, 8);
pkl = (pktlen + 7) & (~7);
if (pkl > pktlen) {
_fmemset(((char *) &ebuf) + vlen, 0, (int) (pkl - vlen));
}
if ((protocolSent == PROTOCOL_RTP) && (pkl > vlen)) {
char *p = (char *) &ebuf;
p[0] |= 0x20; /* Set pad bytes present bit */
p[pkl - 1] = (unsigned char) (pkl - vlen); /* Set pad count at end */
}
des_set_key((des_cblock FAR *) (((protocolSent == PROTOCOL_RTP) ? d->rtpdeskey :
d->vatdeskey) + 1), sched);
des_ncbc_encrypt((des_cblock *) &ebuf,
(des_cblock *) &ebuf, pkl, sched,
(des_cblock *) ivec, DES_ENCRYPT);
slen = pkl - (sizeof(struct soundbuf) - BUFL);
} else {
char twibble[8];
_fmemcpy(twibble, d->deskey + 1, 8);
setkey(twibble);
/* If we're DES encrypting we must round the size of
the data to be sent to be a multiple of 8 so that
the entire DES frame is sent. */
slen = (slen + 7) & (~7);
for (i = 0; i < slen; i += 8) {
/* Apply cipher block chaining within the packet. */
if (i > 0) {
int j;
for (j = 0; j < 8; j++) {
ebuf.buffer.buffer_val[(i + j)] ^=
ebuf.buffer.buffer_val[(i + j) - 8];
}
}
endes(ebuf.buffer.buffer_val + i);
}
ebuf.compression |= fEncDES;
}
}
/* IDEA encryption. */
if ((protocolSent == PROTOCOL_SPEAKFREE) && d->ideakey[0]) {
unsigned short iv[4];
char twibble[16];
_fmemcpy(twibble, d->ideakey + 1, 16);
memset(iv, 0, sizeof(iv));
initcfb_idea(iv, twibble, FALSE);
/* If we're IDEA encrypting we must round the size of
the data to be sent to be a multiple of 8 so that
the entire IDEA frame is sent. */
slen = (slen + 7) & (~7);
ideacfb(ebuf.buffer.buffer_val, (int) slen);
close_idea();
ebuf.compression |= fEncIDEA;
}
/* Blowfish encryption. */
if ((protocolSent == PROTOCOL_SPEAKFREE) && d->blowfish_spec) {
unsigned char iv[8];
memset(iv, 0, sizeof(iv));
/* If we're Blowfish encrypting we must round the size of
the data to be sent to be a multiple of 8 so that
the entire Blowfish frame is sent. */
slen = (slen + 7) & (~7);
BF_cbc_encrypt((unsigned char *) ebuf.buffer.buffer_val,
(unsigned char *) ebuf.buffer.buffer_val,
slen, &(d->blowfishkey), iv, BF_ENCRYPT);
ebuf.compression |= fEncBF;
}
/* PGP session key encryption. */
if ((protocolSent == PROTOCOL_SPEAKFREE) && d->opgpkey[0]) {
unsigned short iv[4];
char twibble[16];
_fmemcpy(twibble, d->opgpkey + 1, 16);
memset(iv, 0, sizeof(iv));
initcfb_idea(iv, twibble, FALSE);
/* If we're IDEA encrypting we must round the size of
the data to be sent to be a multiple of 8 so that
the entire IDEA frame is sent. */
slen = (slen + 7) & (~7);
ideacfb(ebuf.buffer.buffer_val, (int) slen);
close_idea();
ebuf.compression |= fEncPGP;
}
/* One-time pad encryption. */
if ((protocolSent == PROTOCOL_SPEAKFREE) && d->otpFileName[0]) {
for (i = 0; i < slen; i++) {
ebuf.buffer.buffer_val[i] ^= d->otp[i];
}
ebuf.compression |= fEncOTP;
}
pkl = slen + (sizeof(struct soundbuf) - BUFL);
}
#endif
{
int stat, nr;
if (protocolSent == PROTOCOL_SPEAKFREE) {
pkl = lpc10stuff(osb, pkl);
revlong(&osb->compression);
revlong(&osb->buffer.buffer_len);
}
for (nr = 0; nr < ((lpc10compress && (robust > 1)) ? robust : 1); nr++) {
stat = writeOutput(d, (LPSTR) osb, (int) pkl);
if (stat < 0) {
break;
}
}
if (protocolSent == PROTOCOL_SPEAKFREE) {
revlong(&osb->compression);
revlong(&osb->buffer.buffer_len);
lpc10unstuff(osb);
}
if (stat < 0
&& WSAGetLastError() != WSAEINPROGRESS ) {
d->state = d->wantsInput ? SendingLiveAudio : Idle;
d->wantsInput = FALSE;
if (d->hFile != HFILE_ERROR) {
KillTimer(hwnd, 2);
_lclose(d->hFile);
d->hFile = HFILE_ERROR;
}
socketerrorbox(hwnd, d);
return FALSE;
}
}
return TRUE;
}
/* CHANGEAUDIOSTATE -- Change transmitting / receiving state. */
static void changeAudioState(HWND hwnd, LPCLIENT_DATA pClientData)
{
if (pClientData->face_shown) {
LPSTR hname = ((pClientData->uname != NULL) && (pClientData->uname[0]) &&
((pClientData->uname[0] & 0xFF) != 0xFF)) ?
pClientData->uname :
(pClientData->localLoopback ? rstring(IDS_T_LOOPBACK) :
(pClientData->modemConnection ?
rstring(IDS_T_MODEM_CONNECTION) : pClientData->szHost));
if (pClientData->wantsInput) {
char s[MAX_HOST + 20];
strcpy(s, "==> ");
_fstrcat(s, hname);
SetWindowText(hwnd, s);
} else {
SetWindowText(hwnd, hname);
}
} else {
InvalidateRect(hwnd, NULL, FALSE);
UpdateWindow(hwnd);
}
}
/* SHIPSOUNDBUFFER -- Output sound buffer to connection. */
void shipSoundBuffer(HWND hwnd, LPCLIENT_DATA pClientData)
{
if (sqpacket != squelched) {
RECT wr;
POINT cp;
squelched = sqpacket;
GetWindowRect(hwnd, &wr);
GetCursorPos(&cp);
if (PtInRect(&wr, cp)) {
SetCursor((pClientData->wantsInput || broadcasting || bConferencing) ?
(squelched ? boltCursor : earCursor) :
phoneCursor);
UpdateWindow(hwnd); // Change cursor to indicate squelch state
}
}
if (squelched) {
return;
}
if (protocolSent == PROTOCOL_SPEAKFREE) {
sb.compression = fProtocol | (pClientData->ring ? (fSetDest | fDestSpkr) : 0);
pClientData->ring = FALSE;
sb.compression |= pClientData->debugging ? fDebug : 0;
sb.compression |= pClientData->loopback ? fLoopBack : 0;
sb.compression |= compression ? fComp2X : 0;
sb.compression |= gsmcompress ? fCompGSM : 0;
sb.compression |= adpcmcompress ? fCompADPCM : 0;
sb.compression |= lpccompress ? fCompLPC : 0;
sb.compression |= lpc10compress ? fCompLPC10 : 0;
/* Never offer face data to a multicast address. It might be
nice, but the possibility of screw-ups is just too great
given the flakiness of multicast implementations. */
sb.compression |= ((faceFile != HFILE_ERROR) &&
(!IN_MULTICAST(pClientData->inetSock.sin_addr.s_addr))) ? fFaceOffer : 0;
strcpy(sb.sendinghost, ourSendingHost);
}
sendpkt(hwnd, pClientData, &sb);
}
/* SENDSESSIONCTRL -- Send an RTP or VAT session control packet
on the control channel. */
static void sendSessionCtrl(LPCLIENT_DATA pClientData, char *msg, int msgl)
{
char *aux = (char *) &ebuf;
int stat;
#ifdef CRYPTO
if ((!(protocolSent == PROTOCOL_SPEAKFREE)) && pClientData->rtpdeskey[0] &&
!((protocolSent == PROTOCOL_RTP) && waProtNoRTCPCrypt)) {
int vlen;
des_key_schedule sched;
des_cblock ivec;
_fmemset(ivec, 0, 8);
if (protocolSent == PROTOCOL_RTP) {
/* Encrypted RTCP messages are prefixed with 4 random
bytes to prevent known plaintext attacks. */
_fmemcpy(aux, &rtpdesrand, 4);
_fmemcpy(aux + 4, msg, msgl);
msgl += 4;
} else {
_fmemcpy(aux, msg, msgl);
}
/* If we're DES encrypting we must round the size of
the data to be sent to be a multiple of 8 so that
the entire DES frame is sent. This applies only to
VAT, as the code that creates RTCP packets guarantees
they're already padded to a multiple of 8 bytes. */
vlen = msgl;
msgl = (msgl + 7) & (~7);
if (msgl > vlen) {
_fmemset(aux + vlen, 0, msgl - vlen);
}
des_set_key((des_cblock FAR *) (((protocolSent == PROTOCOL_RTP) ?
pClientData->rtpdeskey : pClientData->vatdeskey) + 1), sched);
des_ncbc_encrypt((des_cblock *) aux,
(des_cblock *) aux, msgl, sched,
(des_cblock *) ivec, DES_ENCRYPT);
msg = aux;
}
#endif
if (pClientData->localLoopback) {
stat = loop_sendto(pClientData, msg, msgl,
(LPSOCKADDR) &(pClientData->ctrl), sizeof pClientData->ctrl);
} else {
if ((!useSendNotSendto || waNetNoConnect) && (!waNetUseSend)) {
stat = sendto(pClientData->sControl, msg, msgl, 0,
(LPSOCKADDR) &(pClientData->ctrl), sizeof pClientData->ctrl);
if (stat < 0) {
if (!waNetNoConnect) {
useSendNotSendto = TRUE;
if (hDlgPropeller != NULL) {
SetDlgItemText(hDlgPropeller, IDC_PH_SENDTO, rstring(IDS_T_SEND));
}
}
}
}
/* Careful! Don't "optimise" this to "else if"; we have to be
able to switch-hit when the first sendto() fails above. */
if (useSendNotSendto) {
stat = send(pClientData->sControl, msg, msgl, 0);
}
}
propeller(IDC_PH_PACKETS_SENT, ++packetsSent);
}
/* CREATESOUNDBUFFER -- Create a standard format sound buffer
with selected compression modes from a
set of raw samples received from the audio
input port. Special gimmick: align==0 means
the data are already in place in mu-law
encoding (rate==8000 only). This allows fast
processing of mu-law encoded sound files. */
void createSoundBuffer(LPSTR buffer, WORD buflen, DWORD channels,
DWORD rate, DWORD bytesec, WORD align)
{
int knownFormat = FALSE;
// If the spectrum display is open, let it see the raw samples
spectrumUpdate(buffer, buflen, channels, rate, bytesec, align, FALSE);
if (rate == 8000) {
if (align == 2) {
LONG i;
int j;
for (i = j = 0; i < (LONG) buflen / align; i++) {
sb.buffer.buffer_val[j++] = audio_s2u((((WORD FAR *) buffer)[i]));
}
} else if (align == 1) { // align == 1
LONG i;
int j;
for (i = j = 0; i < (LONG) buflen; i++) {
sb.buffer.buffer_val[j++] = audio_c2u((((BYTE FAR *) buffer)[i]));
}
} else { // (align == 0) already stored in mu-law encoding
align = 1;
}
sb.buffer.buffer_len = buflen / align;
knownFormat = TRUE;
} else if (rate == 11025 && align == 2) {
LONG i;
int j, k;
for (i = j = k = 0; i < (LONG) (buflen / align); i++) {
if ((k & 3) != 2 && ((i % 580) != 579)) {
sb.buffer.buffer_val[j++] = audio_s2u((((WORD FAR *) buffer)[i]));
}
k = (k + 1) % 11;
}
sb.buffer.buffer_len = j;
knownFormat = TRUE;
} else if (rate == 11025 && align == 1) {
LONG i;
int j, k;
for (i = j = k = 0; i < (LONG) (buflen / align); i++) {
if ((k & 3) != 2 && ((i % 580) != 579)) {
sb.buffer.buffer_val[j++] = audio_c2u((((BYTE FAR *) buffer)[i]));
}
k = (k + 1) % 11;
}
sb.buffer.buffer_len = j;
knownFormat = TRUE;
}
sqpacket = FALSE;
if (knownFormat) {
if (voxmode != IDM_VOX_NONE) {
LONG i;
long alevel = 0;
static long voxSampleCountdown;
int j, thresh;
thresh = (int) exp(log(32767.0) * ((1000 - noise_threshold) / 1000.0));
for (i = 0, j = 0; i < sb.buffer.buffer_len; i++, j++) {
int samp = audio_u2s(sb.buffer.buffer_val[j]);
if (samp < 0) {
samp = -samp;
}
alevel += samp;
}
alevel /= sb.buffer.buffer_len;
//{char s[132]; sprintf(s, "Nt = %d, Thresh = %d, Max = %d, Alevel = %ld, VU = %.2g\r\n",
//noise_threshold, thresh, maxsamp, alevel,
//log((double) alevel) / log(32767.0)); OutputDebugString(s);}
voxMonitorUpdate(alevel, 0);
if (alevel < thresh) {
if (voxSampleCountdown <= 0) {
sqpacket = TRUE;
sb.buffer.buffer_len = 0;
return;
}
voxSampleCountdown -= sb.buffer.buffer_len;
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -