<?xml version="1.0" encoding="UTF-8"?><!-- generator="wordpress.com" -->
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	>

<channel>
	<title>socket &amp;laquo; WordPress.com Tag Feed</title>
	<link>http://en.wordpress.com/tag/socket/</link>
	<description>Feed of posts on WordPress.com tagged "socket"</description>
	<pubDate>Fri, 27 Nov 2009 22:33:03 +0000</pubDate>

	<generator>http://en.wordpress.com/tags/</generator>
	<language>en</language>

<item>
<title><![CDATA[HttpRequest in Oracle SQL über Java Function]]></title>
<link>http://rhde.wordpress.com/2009/11/26/httprequest-in-oracle-sql-uber-java-function/</link>
<pubDate>Thu, 26 Nov 2009 15:35:31 +0000</pubDate>
<dc:creator>rhde</dc:creator>
<guid>http://rhde.wordpress.com/2009/11/26/httprequest-in-oracle-sql-uber-java-function/</guid>
<description><![CDATA[Mittel Java kann Oracle nahezu beliebig aufgebohrt werden. Zunächst eine Klasse zum Laden von Websei]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Mittel Java kann Oracle nahezu beliebig aufgebohrt werden.</p>
<p>Zunächst eine Klasse zum Laden von Webseiten per URL:</p>
<pre>
create or replace and compile java source named java_http
as
import java.net.*;
import java.io.*;
public class java_http {
  public static String get(String url) throws Exception {
    URL u = new URL(url);
    URLConnection c = u.openConnection();
    c.setDoOutput(true);
    if (c instanceof HttpURLConnection) {
       ((HttpURLConnection)c).setRequestMethod("GET");
    }
    OutputStreamWriter out = new OutputStreamWriter(
      c.getOutputStream()
    );
    out.close();
    BufferedReader in = new BufferedReader(
      new InputStreamReader(
        c.getInputStream()
      )
    );
    String result = "";
    String s = null;
    while ((s = in.readLine()) != null) {
      result += s;
    }
    in.close();
    return result;
  }
}
</pre>
<p>Für diese Klasse eine Stored Function in Oracle definieren:</p>
<pre>
create or replace function javahttpget(p_string in varchar2)
return varchar2
as language java name 'java_http.get(java.lang.String) return java.lang.String';
</pre>
<p>Testaufruf:</p>
<pre>
select javahttpget('http://www.oracle.com/') from dual;
</pre>
<p>Fehler wegen Berechtigung:</p>
<pre>
ORA-29532: Java-Aufruf durch nicht abgefangene Java-Exception beendet:
java.security.AccessControlException: the Permission (java.net.SocketPermission
www.oracle.com resolve) has not been granted to SCOTT. The PL/SQL to grant this
is dbms_java.grant_permission( 'SCOTT', 'SYS:java.net.SocketPermission','www.oracle.com', 'resolve' )
</pre>
<p>Berechtigung vergeben:</p>
<pre>
conn scott as sysdba
exec dbms_java.grant_permission('SCOTT','SYS:java.net.SocketPermission','www.oracle.com','resolve')
exit
select javahttpget('http://www.oracle.com/') from dual;
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[ss: Display Linux TCP / UDP Network and Socket Information]]></title>
<link>http://jobenbissong.wordpress.com/2009/11/26/ss-display-linux-tcp-udp-network-and-socket-information/</link>
<pubDate>Thu, 26 Nov 2009 14:30:18 +0000</pubDate>
<dc:creator>Jo B</dc:creator>
<guid>http://jobenbissong.wordpress.com/2009/11/26/ss-display-linux-tcp-udp-network-and-socket-information/</guid>
<description><![CDATA[The ss command is used to dump socket statistics. It allows showing information similar to netstat c]]></description>
<content:encoded><![CDATA[The ss command is used to dump socket statistics. It allows showing information similar to netstat c]]></content:encoded>
</item>
<item>
<title><![CDATA[Proxy List Checker &amp; Updater]]></title>
<link>http://codeaddicts.wordpress.com/2009/11/19/proxy-list-checker-updater/</link>
<pubDate>Thu, 19 Nov 2009 15:58:40 +0000</pubDate>
<dc:creator>guidj0s</dc:creator>
<guid>http://codeaddicts.wordpress.com/2009/11/19/proxy-list-checker-updater/</guid>
<description><![CDATA[Heya. This is another perl project, and it might be handy. If you use the internet a lot, you may ev]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Heya. This is another perl project, and it might be handy. If you use the internet a lot, you may eventually build and save huge proxy lists. The problem is, and this is especially true if your list consists of free proxy servers, the number of servers going on and offline all the time is really high, so sometimes it can be annoying to find a good working one. This is what this tool&#8217;s for. It&#8217;ll read a proxy list containing IP:PORT pairs and try a connection on each of them, for a specified number of seconds. If the timeout is reached, the proxy is considered temporarily dead and isn&#8217;t logged. If it connects, the program prints out the pair and logs it to the updated list. The list contains the date and time of execution within its file name. The bigger the proxy list the better, for obvious reasons, but you shouldn&#8217;t delete the original one after running a check. Proxy servers may spring back to life after a little while, so it can&#8217;t hurt to just leave them all there in the original list.</p>
<p><strong>The Code</strong></p>
<p>Modify this to your liking, it&#8217;s simple and straightforward. It&#8217;ll spawn 1000 (woot!) threads per &#8220;round&#8221;, which will each try to connect to a server socket (the proxy server). Change this if you like. Here it is:</p>
<pre>#!/usr/bin/perl

use IO::Socket;
use Threads;

#-----------------------------------+
# guidjos' Proxy List Checker v1.1  &#124;
#-----------------------------------+

if (@ARGV &#60; 1){

 print "\n\n\n   Failed. Usage: $0 [proxylisttxtfile] [timeout(seconds)].  \n\n";
 print "         If no timeout is specified, default == 4 will be used.\n\n\n guidj0s\n";
 exit;
}

@hora = localtime;
$nomelista = "proxylist_$hora[3]-$hora[4]--$hora[2]h$hora[1]m.log";
open(novalista, "&#62;&#62;$nomelista");     # I know, I know.

if ($ARGV[1]){
 $tout = $ARGV[1];
}
else{
 $tout = 4;
}

sub testaservidor{

 my($ip, $falha) = @_;

 my $sockteste = IO::Socket::INET-&#62;new(
  PeerAddr =&#62; $ip,
  Proto =&#62; 'tcp',
  Timeout =&#62; $falha,
  Reuse =&#62; 1
 );

 if ($sockteste){
  $sockteste-&#62;close();
  print "    $ip responded.\n\n";
  print novalista "$ip";
  return 1;
 }
 else{
  print "  $ip is dead.\n\n";
  return 0;
 }
}

open(dados, $ARGV[0]) &#124;&#124; die("\n\n    proxy list file specified was invalid\n\n\n");
@proxies = &#60;dados&#62;;
close dados;

my $atual = 1;
my $vivos;

print "\n\n Starting to check proxy servers...\n\n\n ";

while ($atual &#60;= $#proxies){
 for my $quantas (1..1000){
  if ($atual &#60;= $#proxies){
   my $crianca = threads-&#62;new(\&#38;testaservidor, $proxies[$atual-1], $tout);
   $atual++;
  }
 }
 foreach (threads-&#62;list){
  $resultado = $_-&#62;join;
  if ($resultado){
   $vivos++;
  }
 } 
}

close novalista;
print "\n\n Done.\n\n $vivos out of $#proxies servers responded and were\n  logged to $nomelista\n\n\n";</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[3D Power Socket Powers 5-Devices Simultaneously]]></title>
<link>http://addicts4gadgets.wordpress.com/2009/11/18/3d-power-socket-powers-5-devices-simultaneously/</link>
<pubDate>Wed, 18 Nov 2009 19:11:17 +0000</pubDate>
<dc:creator>swiff88</dc:creator>
<guid>http://addicts4gadgets.wordpress.com/2009/11/18/3d-power-socket-powers-5-devices-simultaneously/</guid>
<description><![CDATA[Art Lebedev reveals the 3D Power Socket, featuring a unique design that pops open to reveal 5 electr]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a href="http://addicts4gadgets.wordpress.com/files/2009/11/3d_power_socket.jpg"><img class="alignnone size-medium wp-image-106" title="3d_power_socket" src="http://addicts4gadgets.wordpress.com/files/2009/11/3d_power_socket.jpg?w=245" alt="" width="245" height="300" /></a></p>
<p>Art Lebedev reveals the 3D Power Socket, featuring a unique design that pops open to reveal 5 electrical outlets at the push of a button. Pricing and availability have not yet been announced. <a href="http://www.techeblog.com/elephant/photo.phtml?post_key=156737&#38;photo_key=29646">Click here</a> for first picture in gallery.</p>
<p><span style="font-size:xx-small;">[via <a rel="nofollow" href="http://www.toxel.com/tech/2009/11/17/rozetkus-3d-power-socket/" target="_blank">Toxel</a>]</span></p>
<p><a href="http://www.techeblog.com/elephant/photo.phtml?post_key=156737&#38;photo_key=29649"><img src="http://media.techeblog.com/elephant//ul/29649-60x-a_4.jpg" alt="Photo " /></a><a href="http://www.techeblog.com/elephant/photo.phtml?post_key=156737&#38;photo_key=29646"><img src="http://media.techeblog.com/elephant//ul/29646-60x-a_1.jpg" alt="Photo " /></a><a href="http://www.techeblog.com/elephant/photo.phtml?post_key=156737&#38;photo_key=29647"><img src="http://media.techeblog.com/elephant//ul/29647-60x-a_2.jpg" alt="Photo " /></a><a href="http://www.techeblog.com/elephant/photo.phtml?post_key=156737&#38;photo_key=29648"><img src="http://media.techeblog.com/elephant//ul/29648-60x-a_3.jpg" alt="Photo " /></a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Multithreaded Perl Portscanner]]></title>
<link>http://codeaddicts.wordpress.com/2009/11/15/multithreaded-perl-portscanner/</link>
<pubDate>Sun, 15 Nov 2009 00:33:06 +0000</pubDate>
<dc:creator>guidj0s</dc:creator>
<guid>http://codeaddicts.wordpress.com/2009/11/15/multithreaded-perl-portscanner/</guid>
<description><![CDATA[While learning sockets in Perl (to put it more acurately, while learning the IO::Socket module), I c]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>While learning sockets in Perl (to put it more acurately, while learning the IO::Socket module), I came across a few implementations of Perl portscanners which, even though functional, were far from practical. I know, I know, you can just get Nmap if you&#8217;re looking for a good portscanner, but hey, you <strong>can</strong> build your own scanner and make it decent.</p>
<p>The implementations I often found (there were also some php versions) were too slow because they worked by looping through the port numbers and trying them sequentially. All I did was create some threads to speed things up, and the resulting speed is actually acceptable. The following code loops through the port range specified, creating rounds of 30 threads to test the ports by calling the &#8220;testarporta()&#8221; sub routine on the current iteration&#8217;s port.</p>
<p>On to the code:</p>
<pre>
<pre>#!/usr/bin/perl
use IO::Socket;
use Threads;

#+---------------------------------------------------------+
#&#124;                                                         &#124;
#&#124;               Fanatic Port Scanner v 1.0                &#124;
#&#124;                  c0d3d by guidj0s                       &#124;
#&#124;                                                         &#124;
#+--:: About ::--------------------------------------------+
#&#124;							   &#124;
#&#124;     Spawns 30 threads per round (more than enough).     &#124;
#&#124;  							   &#124;
#&#124;							   &#124;
#&#124;	usage:						   &#124;
#&#124;							   &#124;
#&#124;	fanatic.pl [ip] [startport] [endport]		   &#124;
#&#124;                                                         &#124;
#+---------------------------------------------------------+

sub testarporta{
  my $tentar = new IO::Socket::INET (
  	PeerAddr =&#62; $_[0],
  	PeerPort =&#62; $_[1],
  	Proto =&#62; 'tcp',
	Timeout =&#62; '1'
  );

  if ($tentar) {
  	print "$_[1] ";
  	$portaberta = $_[1];
  	open(logar, '&#62;&#62;fanatic_scanresults.txt');
  	print logar "$portaberta ";
  	close logar;
	close($tentar);
  }

}

if (@ARGV &#60; 3){

	die "\n\n\n    Failed. Usage: $0 [ip] [startport] [endport]\n\n\n";

}

my ($ip, $pi, $pf) = @ARGV;

print "\n\n -------------------------------:: Fanatic Port Scanner by guidj0s ::-------\n\n";
print " Working...\n\n\n  Open Ports: ";

open(scanlog, '&#62;&#62;fanatic_scanresults.log');
print scanlog "\n\n\n-----------:: Last Scan Results for $ip ::--------------\n\n";
print scanlog "\nPort Range Selected: $pi-$pf";
print scanlog "\n\n\nOpen Ports: ";
close scanlog;

while ($pi &#60;= $pf){
	for my $controle (1..30){
		my $agente = threads-&#62;new(\&#38;testarporta, $ip, $pi);
		$pi++;
	}
	foreach (threads-&#62;list){
		$_-&#62;join;
	}
}

	print "\n\n\t\t\tScan finished.\n\n";</pre>
</pre>
<p>As you can see, the ports found open are logged to fanatic_scanresults.log. If you looked at the code you realized a port is considered &#8220;open&#8221; only when a connection can be established on it.</p>
<p>&#160;</p>
<p>&#160;</p>
<p><strong>The Win32 GUI version</strong></p>
<p>
<br />
I did make one. I coded it using the Win32::GUI module. I know TK would have been a better option (as I found out quite soon), but that&#8217;s what I went with and I really don&#8217;t think it&#8217;s worth the hassle to migrate (I&#8217;m not working on it again any time soon).</p>
<p>
<br />
 As you may know, Win32::GUI isn&#8217;t thread safe. In this case, whenever I tried to access a Win32::GUI object from within a child thread, the program crashed. I solved the problem by creating a shared variable ($aberta), which is updated everytime an open port is found. I also created a control variable ($ultima), which is used to check whether the last value printed out/logged was already printed or if the value currently stored in $aberta has already been handled (so I only need to print it when $aberta != $ultima. After doing so, I update $ultima with the current value stored in $aberta), and then access the Win32::GUI element from the main thread.</p>
<p>
<br />
 I added a functionality to the program, which is the option of providing a portlist plain-text file to scan for specific ports only. Enough talking, here&#8217;s the code: <a href="http://guidjos.justfree.com/fntcgui.txt" target="fntcgui">http://guidjos.justfree.com/fntcgui.txt</a></p>
<p>
<br />
Now that I look at my code again, I see there&#8217;s a silly mistake. You should never access files like I did here:</p>
<p>
</p>
<pre>
open(scanlog, "&#62;&#62;$logto");
</pre>
<p>
<br />
But I&#8217;ll leave this for another post, as this one&#8217;s long enough. The handling of user-input related mistakes isn&#8217;t really thorough either, so feel free to improve the code (sharing the new version would be cool, I might give you some space to talk about it and share your code here on the blog <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' />  ).</p>
<p></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[come as you are]]></title>
<link>http://ahanbesol.wordpress.com/2009/11/12/come-as-you-are/</link>
<pubDate>Fri, 13 Nov 2009 04:35:51 +0000</pubDate>
<dc:creator>Sarah</dc:creator>
<guid>http://ahanbesol.wordpress.com/2009/11/12/come-as-you-are/</guid>
<description><![CDATA[am- The window reflects blue skies and the warmth of the sun, all the while little annoyances bounce]]></description>
<content:encoded><![CDATA[am- The window reflects blue skies and the warmth of the sun, all the while little annoyances bounce]]></content:encoded>
</item>
<item>
<title><![CDATA[Histeria]]></title>
<link>http://igorborges.wordpress.com/2009/11/11/histeria/</link>
<pubDate>Thu, 12 Nov 2009 01:58:09 +0000</pubDate>
<dc:creator>Borges</dc:creator>
<guid>http://igorborges.wordpress.com/2009/11/11/histeria/</guid>
<description><![CDATA[Quarta-feira, 11 de Novembro de 2009, 23h20 Mais um papo filosófico com o Wendel. Como esse cara con]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Quarta-feira, 11 de Novembro de 2009, 23h20</p>
<p>Mais um papo filosófico com o Wendel. Como esse cara consegue pensar em tantas coisas, numa diversidade como essa? O aprender é a verdade absoluta do mundo. Tudo gira em torno disso. Ter alguém que te ensine, e você aprende o que for útil pra você. Claro, ensinar também, o que você acha ser importante. &#8220;<em>Cada um tem sua própria sede</em>&#8220;.</p>
<p>Agora me lembrei do Felipe aqui em casa vestido com uma camisa do São Paulo. Tudo de uma aposta que ele fez com a Thais. Me pergunto se ele mudará de time só porque ela é são-paulina.. nesse momento, Palmeiras acaba de empatar o jogo, o que deixa o tricolor em segundo lugar na classificação do campeonato que ele vencerá. <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Ficamos a aula de português inteira resumindo o texto que leremos aos cegos. Enrolamos o máximo possível, é claro; lemos algumas notícias sobre o apagão de ontem, e todo aquele caos (ou conspiração governamental) na usina de Itaipu. Na de matemática, pra variar só mais um pouquinho, fizemos exercícios, e o Dimas, sempre com tesão de dar aula, animado com isso (acabo de perceber que escrevo muito na <del datetime="2009-11-17T00:49:14+00:00">terceira pessoa</del> primeira pessoa do plural, e não há necessidade, uma vez que isto é um diário <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_surprised.gif' alt=':o' class='wp-smiley' />  ). Entreguei aquele clipe horrível na aula de artes e vi uma apresentação sobre histeria do Andrey. Não gostei do assunto, já vi outros melhores sobre psicologia.</p>
<p>Almoço, Barão. Coca gelada. Depois, expo do último grupo da informática B. O programa delas não funcionou, mas acho que os professores pegarão menos pesado. Afinal, era um software bem difícil, e só o grupo do Igor fez o socket a mão, não pegando nada pronto da Internet. Mas eu sei que elas tentaram, porque as vi muitas vezes fazendo o dito cujo. Nessa semana e pelas próximas duas, devo ter aula normal. Aulas e provas, infelizmente. Ainda tenho que ler um livro e fazer um site para o dia dezoito. Mas em Dezembro, deve ser só farra. <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> </p>
<p>Não encontrei um espaço, mas tinha que colocar esse evento aqui: hoje, no carro, Felipe, melzinho. Ihh, pegou mal. Calma. Felipe estava comendo aquele mel que vem em pacotinhos. Uma dica para uma boa degustação: enfia tudo na boca e vá mastigando. É satisfação garantida! <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_mrgreen.gif' alt=':mrgreen:' class='wp-smiley' /> </p>
<p>23h55</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Testing portaudio and speex - part 4]]></title>
<link>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-4/</link>
<pubDate>Wed, 11 Nov 2009 00:35:57 +0000</pubDate>
<dc:creator>slworkthings</dc:creator>
<guid>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-4/</guid>
<description><![CDATA[Continue. AudioEngine header file: #ifndef _AUDIOENGINE_H_ #define _AUDIOENGINE_H_ #include &#8220;m]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Continue.</p>
<p>AudioEngine header file:<br />
#ifndef _AUDIOENGINE_H_<br />
#define _AUDIOENGINE_H_</p>
<p>#include &#8220;mysocket.h&#8221;<br />
#include &#8220;portaudio.h&#8221;<br />
#include &#8220;san_speex.h&#8221;<br />
#include &#60;qwidget.h&#62;</p>
<p>#define SAMPLE_RATE  16000<br />
#define FRAMES_PER_BUFFER 320<br />
#define PA_SAMPLE_TYPE  paInt16<br />
typedef short SAMPLE;<br />
#define SAMPLE_SILENCE  (0)<br />
#define NUM_CHANNELS    1<br />
class AudioEngine;<br />
typedef struct<br />
{<br />
    SanSpeexEnc     speexenc;<br />
    SAMPLE          recordbuffer[FRAMES_PER_BUFFER * NUM_CHANNELS];<br />
    char            encodedBufPlus8[FRAMES_PER_BUFFER * NUM_CHANNELS * 2 ];<br />
    SanSpeexDec     speexdec;<br />
    SAMPLE          playbackbuffer[FRAMES_PER_BUFFER * NUM_CHANNELS];<br />
    AudioEngine    *obj;<br />
} paTestData;<br />
//============================================<br />
class AudioEngine : public QWidget<br />
{<br />
    Q_OBJECT<br />
public:<br />
    AudioEngine();<br />
    virtual ~AudioEngine();</p>
<p>    void recvPlaybackDataIn(const QByteArray&#38; ba);<br />
    void setSelfLoop(bool flag);<br />
    bool isSelfLoop() const { return m_isSelfLoop; }<br />
protected:<br />
    virtual void closeEvent(QCloseEvent *);</p>
<p>private slots:<br />
    void slotReceivedData(const QByteArray&#38;);<br />
    void slotReceivedHandshake(const QString&#38; hisId);</p>
<p>private:<br />
    static int s_recordCallback(const void *inputBuffer, void *outputBuffer,<br />
                                unsigned long framesPerBuffer,<br />
                                const PaStreamCallbackTimeInfo* timeInfo,<br />
                                PaStreamCallbackFlags statusFlags,<br />
                                void *userData);<br />
    static int s_playCallback(const void *inputBuffer, void *outputBuffer,<br />
                              unsigned long framesPerBuffer,<br />
                              const PaStreamCallbackTimeInfo* timeInfo,<br />
                              PaStreamCallbackFlags statusFlags,<br />
                              void *userData);<br />
    static int s_loopCallback(const void *inputBuffer, void *outputBuffer,<br />
                              unsigned long framesPerBuffer,<br />
                              const PaStreamCallbackTimeInfo* timeInfo,<br />
                              PaStreamCallbackFlags statusFlags,<br />
                              void *userData);</p>
<p>    bool initPa();<br />
    bool unInitPa();<br />
    bool startPaRecorder(int id);<br />
    bool startPaPlayback(int id);<br />
    bool stopPaRecorder();<br />
    bool stopPaPlayback();<br />
    bool startPaRecorderPlaybackLoop(int inputId, int outputId);<br />
    bool stopPaRecorderPlaybackLoop();</p>
<p>    void sendRecordDataOut(char *buf, int len);</p>
<p>private:<br />
    MyServerSocket    *m_serverSocket;<br />
    QString            m_recorderId;<br />
    QString            m_playbackId;</p>
<p>    PaStream          *m_streamIn, *m_streamOut;<br />
    PaError            m_errIn, m_errOut;<br />
    int                m_inputId, m_outputId;</p>
<p>    paTestData         m_data;<br />
    bool               m_isSelfLoop;<br />
};</p>
<p>#endif // _AUDIOENGINE_H_</p>
<p> AudioEngine source file:</p>
<p>#include &#8220;audioengine.h&#8221;<br />
#include &#60;qapplication.h&#62;<br />
#include &#60;windows.h&#62;<br />
//#include &#60;mmddk.h&#62;</p>
<p>//===================================<br />
AudioEngine::AudioEngine()<br />
            :QWidget(),<br />
             m_serverSocket(0),<br />
             m_recorderId(QString::null),<br />
             m_playbackId(QString::null),<br />
             m_streamIn(0),<br />
             m_streamOut(0),<br />
             m_errIn(paNoError),<br />
             m_errOut(paNoError),<br />
             m_inputId(-1),<br />
             m_outputId(-1),<br />
             m_isSelfLoop(true)<br />
{<br />
    qDebug(&#8220;AE ctor&#8221;);<br />
    m_serverSocket = new MyServerSocket();<br />
    connect(m_serverSocket, SIGNAL(fireReceivedData(const QByteArray&#38;)),<br />
                            SLOT(slotReceivedData(const QByteArray&#38;)));<br />
    connect(m_serverSocket, SIGNAL(fireReceivedHandshake(const QString&#38;)),<br />
                            SLOT(slotReceivedHandshake(const QString&#38;)));<br />
    qDebug(&#8220;m_serverSocket port = %d&#8221;, m_serverSocket-&#62;port());</p>
<p>    resize(100, 100);<br />
    move(0, 0);<br />
    hide();</p>
<p>    m_data.obj = this;<br />
    m_data.speexdec.setSanSpeexEnc(&#38;m_data.speexenc);<br />
    initPa();<br />
}</p>
<p>AudioEngine::~AudioEngine()<br />
{<br />
    qDebug(&#8220;AE dtor&#8221;);<br />
    delete m_serverSocket;<br />
    m_serverSocket = 0;<br />
    unInitPa();<br />
}</p>
<p>void AudioEngine::closeEvent(QCloseEvent *)<br />
{<br />
    qDebug(&#8220;AE::closeEvent&#8221;);<br />
    qApp-&#62;exit(0);<br />
}</p>
<p>void AudioEngine::slotReceivedData(const QByteArray&#38; ba)<br />
{<br />
    qDebug(&#8220;AE::slotRecvData = %d&#8221;, ba.size());<br />
    const char *data = ba.data();<br />
    if (ba.size() &#62;= 4 &#38;&#38; data[0] == &#8216;c&#8217; &#38;&#38; data[1] == &#8216;m&#8217; &#38;&#38; data[2] == &#8216;d&#8217;)<br />
    {<br />
        char cmd = data[3];<br />
        switch (cmd)<br />
        {<br />
        case &#8216;1&#8242;: //return device list;   dev1\ndev2\n&#8230;<br />
            {<br />
                QString devList(ba);<br />
                devList = devList.mid(4);<br />
                qDebug(&#8220;1. DevList = &#8221; + devList);<br />
            }<br />
            break;<br />
        case &#8216;2&#8242;: //set recorder device;  devname<br />
            {<br />
                QString devName(ba);<br />
                devName = devName.mid(4);<br />
                qDebug(&#8220;2. RecorderDevice = &#8221; + devName);<br />
                m_inputId = devName.toInt();<br />
            }<br />
            break;<br />
        case &#8216;3&#8242;: //set playback device; devname<br />
            {<br />
                QString devName(ba);<br />
                devName = devName.mid(4);<br />
                qDebug(&#8220;3. PlaybackDevice = &#8221; + devName);<br />
                m_outputId = devName.toInt();<br />
            }<br />
            break;<br />
        case &#8216;4&#8242;: //start recorder<br />
            qDebug(&#8220;4. Start Recording&#8221;);<br />
            if (!m_isSelfLoop)<br />
            {<br />
                if (m_inputId != -1 &#38;&#38; m_streamIn == 0)<br />
                    startPaRecorder(m_inputId);<br />
            }<br />
            else<br />
            {<br />
                if (m_inputId != -1 &#38;&#38; m_outputId != -1 &#38;&#38; m_streamIn == 0)<br />
                    startPaRecorderPlaybackLoop(m_inputId, m_outputId);<br />
            }<br />
            break;<br />
        case &#8216;5&#8242;: //start playback<br />
            qDebug(&#8220;5. Start Playback&#8221;);<br />
            if (!m_isSelfLoop)<br />
            {<br />
                if (m_outputId != -1 &#38;&#38; m_streamOut == 0)<br />
                    startPaPlayback(m_outputId);<br />
            }<br />
            else<br />
            {<br />
                if (m_inputId != -1 &#38;&#38; m_outputId != -1 &#38;&#38; m_streamIn == 0)<br />
                    startPaRecorderPlaybackLoop(m_inputId, m_outputId);<br />
            }<br />
            break;<br />
        case &#8216;6&#8242;: //stop recorder<br />
            qDebug(&#8220;6. Stop Recording&#8221;);<br />
            if (!m_isSelfLoop)<br />
                stopPaRecorder();<br />
            else<br />
                stopPaRecorderPlaybackLoop();<br />
            break;<br />
        case &#8216;7&#8242;: //stop playback<br />
            qDebug(&#8220;7. Stop Playback&#8221;);<br />
            if (!m_isSelfLoop)<br />
                stopPaPlayback();<br />
            else<br />
                stopPaRecorderPlaybackLoop();<br />
            break;<br />
        case &#8216;Q&#8217;: //totally exit<br />
            qDebug(&#8220;Q. Quit&#8221;);<br />
            if (m_serverSocket)<br />
                m_serverSocket-&#62;stop();<br />
            show();<br />
            break;<br />
        default:<br />
            break;<br />
        }//switch()<br />
    }//&#8221;cmd&#8221;<br />
    else //binary<br />
    {<br />
    }//binary<br />
}//slotReceivedData()</p>
<p>void AudioEngine::slotReceivedHandshake(const QString&#38; hisId)<br />
{<br />
    qDebug(&#8220;AE::slotRecvHandshake = &#8221; + hisId);<br />
    if (hisId == &#8220;recorder&#8221;)<br />
        m_recorderId = hisId;<br />
    else if (hisId == &#8220;playback&#8221;)<br />
        m_playbackId = hisId;<br />
}//slotReceivedHandshake()</p>
<p>int AudioEngine::s_recordCallback(const void *inputBuffer, void *outputBuffer,<br />
                                  unsigned long framesPerBuffer,<br />
                                  const PaStreamCallbackTimeInfo* timeInfo,<br />
                                  PaStreamCallbackFlags statusFlags,<br />
                                  void *userData)<br />
{<br />
    paTestData *data = (paTestData*)userData;<br />
    const SAMPLE *rptr = (const SAMPLE*)inputBuffer;<br />
    SAMPLE *wptr = data-&#62;recordbuffer;<br />
    long framesToCalc;<br />
    framesToCalc = framesPerBuffer;<br />
    long i;<br />
    int finished = paContinue;<br />
    bool isSelfLoop = data-&#62;obj-&#62;isSelfLoop();<br />
   <br />
    (void) outputBuffer; /* Prevent unused variable warnings. */<br />
    (void) timeInfo;<br />
    (void) statusFlags;<br />
    (void) userData;</p>
<p>    if( inputBuffer == NULL )<br />
    {<br />
        for( i=0; i&#60;framesToCalc; i++ )<br />
        {<br />
            *wptr++ = SAMPLE_SILENCE;<br />
            if (NUM_CHANNELS == 2)<br />
                *wptr++ = SAMPLE_SILENCE;<br />
        }<br />
    }<br />
    else<br />
    {<br />
        for( i=0; i&#60;framesToCalc; i++ )<br />
        {<br />
            *wptr++ = *rptr++;<br />
            if (NUM_CHANNELS == 2)<br />
                *wptr++ = *rptr++;<br />
        }<br />
    }</p>
<p>    int encSizePlus8 = data-&#62;speexenc.encode(data-&#62;recordbuffer, data-&#62;encodedBufPlus8);<br />
    if (encSizePlus8 &#62; 0)<br />
    {<br />
        int encSizePlus4 = ((int *)data-&#62;encodedBufPlus8)[0];</p>
<p>        //if (!isSelfLoop)<br />
        {<br />
            //send out encodedBufPlus8 to spydonk<br />
            data-&#62;obj-&#62;sendRecordDataOut(data-&#62;encodedBufPlus8, encSizePlus8);<br />
        }</p>
<p>        /*<br />
        if (isSelfLoop)<br />
        {<br />
            //when seedonk receiving some audio buf from server, call following line<br />
            data-&#62;speexdec.put(data-&#62;encodedBufPlus8+4, encSizePlus4);<br />
        }<br />
        */<br />
    }</p>
<p>    return finished;<br />
}//s_recordCallback()</p>
<p>int AudioEngine::s_playCallback(const void *inputBuffer, void *outputBuffer,<br />
                                unsigned long framesPerBuffer,<br />
                                const PaStreamCallbackTimeInfo* timeInfo,<br />
                                PaStreamCallbackFlags statusFlags,<br />
                                void *userData)<br />
{<br />
    paTestData *data = (paTestData*)userData;<br />
    SAMPLE *rptr = data-&#62;playbackbuffer;<br />
    SAMPLE *wptr = (SAMPLE*)outputBuffer;<br />
    int finished = paContinue;<br />
    unsigned int framesLeft = 0;<br />
    int i;<br />
    bool isSelfLoop = data-&#62;obj-&#62;isSelfLoop();</p>
<p>    data-&#62;speexdec.get(rptr);<br />
    framesLeft = framesPerBuffer;</p>
<p>    (void) inputBuffer; /* Prevent unused variable warnings. */<br />
    (void) timeInfo;<br />
    (void) statusFlags;<br />
    (void) userData;</p>
<p>    for( i=0; i&#60;framesPerBuffer; i++ )<br />
    {<br />
        *wptr++ = *rptr++;<br />
        if (NUM_CHANNELS == 2)<br />
            *wptr++ = *rptr++;<br />
    }</p>
<p>    rptr = data-&#62;playbackbuffer;<br />
    data-&#62;speexdec.afterPlayback(rptr, true);</p>
<p>    return finished;<br />
}//s_playCallback()</p>
<p>int AudioEngine::s_loopCallback(const void *inputBuffer, void *outputBuffer,<br />
                                unsigned long framesPerBuffer,<br />
                                const PaStreamCallbackTimeInfo* timeInfo,<br />
                                PaStreamCallbackFlags statusFlags,<br />
                                void *userData)<br />
{<br />
    paTestData *data = (paTestData*)userData;<br />
    const SAMPLE *rptr = (const SAMPLE*)inputBuffer;<br />
    SAMPLE *wptr = (SAMPLE*)outputBuffer;<br />
    SAMPLE *prevPlayPtr = data-&#62;playbackbuffer;<br />
    long framesToCalc;<br />
    framesToCalc = framesPerBuffer;<br />
    long i;<br />
    int finished = paContinue;<br />
   <br />
    (void) outputBuffer; /* Prevent unused variable warnings. */<br />
    (void) timeInfo;<br />
    (void) statusFlags;<br />
    (void) userData;</p>
<p>    //data-&#62;speexenc.playbackEcho(prevPlayPtr, true);</p>
<p>    if( inputBuffer == NULL )<br />
    {<br />
        for( i=0; i&#60;framesToCalc; i++ )<br />
        {<br />
            *wptr++ = SAMPLE_SILENCE;<br />
            //*prevPlayPtr++ = SAMPLE_SILENCE;<br />
            if (NUM_CHANNELS == 2)<br />
            {<br />
                *wptr++ = SAMPLE_SILENCE;<br />
                //*prevPlayPtr++ = SAMPLE_SILENCE;<br />
            }<br />
        }<br />
        return 0;<br />
    }<br />
    else<br />
    {<br />
        for( i=0; i&#60;framesToCalc; i++ )<br />
        {<br />
            *wptr++ = *rptr;<br />
            //*prevPlayPtr++ = *rptr;<br />
            rptr++;<br />
            if (NUM_CHANNELS == 2)<br />
            {<br />
                *wptr++ = *rptr;<br />
                //*prevPlayPtr++ = *rptr;<br />
                rptr++;<br />
            }<br />
        }<br />
    }</p>
<p>    //data-&#62;speexenc.captureEcho(wptr);<br />
    data-&#62;speexenc.captureEcho(wptr, prevPlayPtr);<br />
    for (i=0; i&#60;framesToCalc; i++)<br />
    {<br />
        *prevPlayPtr++ = *wptr++;<br />
    }</p>
<p>    return finished;<br />
}//s_loopCallback()<br />
bool AudioEngine::initPa()<br />
{<br />
    PaError err = Pa_Initialize();<br />
    if (err == paNoError)<br />
    {<br />
        int numDevices = Pa_GetDeviceCount();<br />
        int inputId, outputId;<br />
        int prevHostApi = -1;<br />
        for(int id=0; id&#60;numDevices; id++)            /* Iterate through all devices. */<br />
        {<br />
            const PaDeviceInfo *pdi = Pa_GetDeviceInfo(id);<br />
            if (prevHostApi != pdi-&#62;hostApi)<br />
            {<br />
                const PaHostApiInfo *info = Pa_GetHostApiInfo(pdi-&#62;hostApi);<br />
                qDebug(&#8220;=== HostApi, %d, type=%d, name=%s ====&#8221;, pdi-&#62;hostApi, info-&#62;type, info-&#62;name);<br />
                qDebug(&#8220;=== def I=%d, defO=%d ====&#8221;, info-&#62;defaultInputDevice, info-&#62;defaultOutputDevice);</p>
<p>                prevHostApi = pdi-&#62;hostApi;</p>
<p>            }<br />
            qDebug(&#8220;[%d]=[%s], IChs=%d, OChs=%d&#8221;,<br />
                               id, pdi-&#62;name,<br />
                               pdi-&#62;maxInputChannels,<br />
                               pdi-&#62;maxOutputChannels);</p>
<p>//#define DRV_RESERVED           0&#215;0800<br />
//#define DRV_QUERYDEVICEINTERFACE     (DRV_RESERVED + 12)<br />
//#define DRV_QUERYDEVICEINTERFACESIZE (DRV_RESERVED + 13)</p>
<p>            /*<br />
            if (pdi-&#62;maxInputChannels &#62; 0)<br />
            {<br />
                DWORD pathSize = 0;<br />
                if (waveInMessage((HWAVEIN)id, 0&#215;0800+13,<br />
                                   (DWORD_PTR)&#38;pathSize, 0) != MMSYSERR_NOERROR)<br />
                {<br />
                    qDebug(&#8220;**** pathSize = %d&#8221;, pathSize);<br />
                    char *path = new char[pathSize];<br />
                    memset(path, 0, pathSize);<br />
                    if (waveInMessage((HWAVEIN)id, 0&#215;0800+12,<br />
                                       (DWORD_PTR)path, sizeof(path)) != MMSYSERR_NOERROR)<br />
                    {<br />
                        qDebug(&#8220;**** path = %s&#8221;, path);<br />
                    }<br />
                    delete [] path;<br />
                }<br />
                else<br />
                    qDebug(&#8220;**** ERROR %d&#8221;, id);<br />
            }<br />
            */<br />
        }<br />
    }<br />
    qDebug(&#8220;======================================&#8221;);<br />
    return (err == paNoError);<br />
}</p>
<p>bool AudioEngine::unInitPa()<br />
{<br />
    if (m_streamIn)<br />
        Pa_CloseStream(m_streamIn);<br />
    m_streamIn = 0;<br />
    if (m_streamOut)<br />
        Pa_CloseStream(m_streamOut);<br />
    m_streamOut = 0;</p>
<p>    Pa_Terminate();<br />
    return true;<br />
}</p>
<p>bool AudioEngine::startPaRecorder(int inputId)<br />
{<br />
    PaStreamParameters  inputParameters;</p>
<p>    inputParameters.device = inputId;<br />
    inputParameters.channelCount = NUM_CHANNELS;<br />
    inputParameters.sampleFormat = PA_SAMPLE_TYPE;<br />
    inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputId)-&#62;defaultLowInputLatency;<br />
    inputParameters.hostApiSpecificStreamInfo = NULL;<br />
    qDebug(&#8220;Input Device = [%s], latency = %f&#8221;, Pa_GetDeviceInfo(inputId)-&#62;name, inputParameters.suggestedLatency);</p>
<p>    /* Record some audio. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; */<br />
    m_errIn = Pa_OpenStream(&#38;m_streamIn,<br />
                            &#38;inputParameters,<br />
                            NULL,                  /* &#38;outputParameters, */<br />
                            SAMPLE_RATE,<br />
                            FRAMES_PER_BUFFER*NUM_CHANNELS,<br />
                            paClipOff&#124;paDitherOff,      /* we won&#8217;t output out of range samples so don&#8217;t bother clipping them */<br />
                            AudioEngine::s_recordCallback,<br />
                            &#38;m_data);<br />
    if(m_errIn != paNoError)<br />
        return false;</p>
<p>    m_errIn = Pa_StartStream(m_streamIn);<br />
    if(m_errIn != paNoError)<br />
        return false;<br />
    qDebug(&#8220;Now recording!!&#8221;);<br />
    return true;<br />
}//startPaRecorder()</p>
<p>bool AudioEngine::startPaPlayback(int outputId)<br />
{<br />
    PaStreamParameters  outputParameters;</p>
<p>    outputParameters.device = outputId;<br />
    outputParameters.channelCount = NUM_CHANNELS;<br />
    outputParameters.sampleFormat =  PA_SAMPLE_TYPE;<br />
    outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputId)-&#62;defaultLowOutputLatency;<br />
    outputParameters.hostApiSpecificStreamInfo = NULL;<br />
    qDebug(&#8220;Output Device = [%s], latency = %f&#8221;, Pa_GetDeviceInfo(outputId)-&#62;name, outputParameters.suggestedLatency);</p>
<p>    qDebug(&#8220;Begin playback.&#8221;);<br />
    m_errOut = Pa_OpenStream(&#38;m_streamOut,<br />
                             NULL, /* no input */<br />
                             &#38;outputParameters,<br />
                             SAMPLE_RATE,<br />
                             FRAMES_PER_BUFFER*NUM_CHANNELS,<br />
                             paClipOff&#124;paDitherOff,      /* we won&#8217;t output out of range samples so don&#8217;t bother clipping them */<br />
                             AudioEngine::s_playCallback,<br />
                             &#38;m_data);<br />
    if(m_errOut != paNoError)<br />
        return false;</p>
<p>    m_errOut = Pa_StartStream(m_streamOut);<br />
    if(m_errOut != paNoError )<br />
        return false;<br />
    return true;<br />
}//startPaPlayback()</p>
<p>bool AudioEngine::startPaRecorderPlaybackLoop(int inputId, int outputId)<br />
{<br />
    if (m_streamIn != 0) //already started<br />
        return true;</p>
<p>    PaStreamParameters  inputParameters;<br />
    PaStreamParameters  outputParameters;</p>
<p>    inputParameters.device = inputId;<br />
    inputParameters.channelCount = NUM_CHANNELS;<br />
    inputParameters.sampleFormat = PA_SAMPLE_TYPE;<br />
    inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputId)-&#62;defaultLowInputLatency;<br />
    inputParameters.hostApiSpecificStreamInfo = NULL;<br />
    qDebug(&#8220;Input Device = [%s], latency = %f&#8221;, Pa_GetDeviceInfo(inputId)-&#62;name, inputParameters.suggestedLatency);<br />
    outputParameters.device = outputId;<br />
    outputParameters.channelCount = NUM_CHANNELS;<br />
    outputParameters.sampleFormat =  PA_SAMPLE_TYPE;<br />
    outputParameters.suggestedLatency = Pa_GetDeviceInfo(outputId)-&#62;defaultLowOutputLatency;<br />
    outputParameters.hostApiSpecificStreamInfo = NULL;<br />
    qDebug(&#8220;Output Device = [%s], latency = %f&#8221;, Pa_GetDeviceInfo(outputId)-&#62;name, outputParameters.suggestedLatency);</p>
<p>    /* RecordPlayback Loop some audio. &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; */<br />
    m_errIn = Pa_OpenStream(&#38;m_streamIn,<br />
                            &#38;inputParameters,<br />
                            &#38;outputParameters,<br />
                            SAMPLE_RATE,<br />
                            FRAMES_PER_BUFFER*NUM_CHANNELS,<br />
                            paClipOff&#124;paDitherOff,      /* we won&#8217;t output out of range samples so don&#8217;t bother clipping them */<br />
                            AudioEngine::s_loopCallback,<br />
                            &#38;m_data);<br />
    if(m_errIn != paNoError)<br />
        return false;</p>
<p>    m_errIn = Pa_StartStream(m_streamIn);<br />
    if(m_errIn != paNoError)<br />
        return false;<br />
    qDebug(&#8220;Now looping!!&#8221;);<br />
    return true;<br />
}//startPaRecorderPlaybackLoop()</p>
<p>bool AudioEngine::stopPaRecorder()<br />
{<br />
    if (m_streamIn)<br />
        Pa_CloseStream(m_streamIn);<br />
    m_streamIn = 0;<br />
    return true;<br />
}//stopPaRecorder()</p>
<p>bool AudioEngine::stopPaPlayback()<br />
{<br />
    if (m_streamOut)<br />
        Pa_CloseStream(m_streamOut);<br />
    m_streamOut = 0;<br />
    return true;<br />
}//stopPaPlayback()</p>
<p>bool AudioEngine::stopPaRecorderPlaybackLoop()<br />
{<br />
    return stopPaRecorder();<br />
}//stopPaRecorderPlaybackLoop()</p>
<p>void AudioEngine::sendRecordDataOut(char *buf, int len)<br />
{<br />
    if (m_isSelfLoop)<br />
        return;</p>
<p>    if (!m_recorderId.isNull() &#38;&#38; m_serverSocket)<br />
    {<br />
        QByteArray ba;<br />
        ba.setRawData(buf, len);<br />
        m_serverSocket-&#62;send(ba, m_recorderId);<br />
        ba.resetRawData(buf, len);<br />
    }<br />
}//sendRecordDataOut()</p>
<p>void AudioEngine::recvPlaybackDataIn(const QByteArray&#38; ba)<br />
{<br />
    if (m_isSelfLoop)<br />
        return;</p>
<p>    //buffer:<br />
    //  encodedBufSize + 4 &#124; timestamp &#124; encodedBuf<br />
    // &#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211;<br />
    //  4                  &#124;  4        &#124; encodedBufSize &#8211; 4<br />
    int len = 0;<br />
    if (!m_playbackId.isNull() &#38;&#38; (len = ba.size()) &#62; <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /><br />
    {<br />
        char *buf = new char [len];<br />
        memcpy(buf, ba.data(), len);<br />
        m_data.speexdec.put(buf+4, len-4); //encodedBufWithTimeStamp<br />
        delete [] buf;<br />
        buf = 0;<br />
    }<br />
}//recvPlaybackDataIn()</p>
<p>void AudioEngine::setSelfLoop(bool flag)<br />
{<br />
    m_isSelfLoop = flag;<br />
    if (m_isSelfLoop)<br />
    {<br />
        m_recorderId = &#8220;recorder&#8221;;<br />
        m_playbackId = &#8220;playback&#8221;;<br />
    }<br />
}</p>
<p>&#160;</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Testing portaudio and speex - part 3]]></title>
<link>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-3/</link>
<pubDate>Wed, 11 Nov 2009 00:34:31 +0000</pubDate>
<dc:creator>slworkthings</dc:creator>
<guid>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-3/</guid>
<description><![CDATA[Continue. speex header file: #ifndef _SAN_SPEEX_H_ #define _SAN_SPEEX_H_ //copy from speex_jitter_bu]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Continue.</p>
<p>speex header file:</p>
<p>#ifndef _SAN_SPEEX_H_<br />
#define _SAN_SPEEX_H_<br />
//copy from speex_jitter_buffer.h(.c)<br />
#include &#60;speex/speex_jitter.h&#62;<br />
#include &#60;speex/speex.h&#62;<br />
#include &#60;speex/speex.h&#62;<br />
#include &#60;speex/speex_jitter.h&#62;<br />
#include &#60;speex/speex_preprocess.h&#62;<br />
#include &#60;speex/speex_echo.h&#62;<br />
#ifdef __cplusplus<br />
extern &#8220;C&#8221; {<br />
#endif</p>
<p>/** @defgroup SpeexJitter SpeexJitter: Adaptive jitter buffer specifically for Speex<br />
 *  This is the jitter buffer that reorders UDP/RTP packets and adjusts the buffer size<br />
 * to maintain good quality and low latency. This is a simplified version that works only<br />
 * with Speex, but is much easier to use.<br />
 *  @{<br />
*/</p>
<p>/** Speex jitter-buffer state. Never use it directly! */<br />
typedef struct SpeexJitter {<br />
   SpeexBits current_packet;         /**&#60; Current Speex packet */<br />
   int valid_bits;                   /**&#60; True if Speex bits are valid */<br />
   JitterBuffer *packets;            /**&#60; Generic jitter buffer state */<br />
   void *dec;                        /**&#60; Pointer to Speex decoder */<br />
   spx_int32_t frame_size;           /**&#60; Frame size of Speex decoder */<br />
} SpeexJitter;</p>
<p>/** Initialise jitter buffer<br />
 *<br />
 * @param jitter State of the Speex jitter buffer<br />
 * @param decoder Speex decoder to call<br />
 * @param sampling_rate Sampling rate used by the decoder<br />
*/<br />
void speex_jitter_init(SpeexJitter *jitter, void *decoder, int sampling_rate);</p>
<p>/** Destroy jitter buffer */<br />
void speex_jitter_destroy(SpeexJitter *jitter);</p>
<p>/** Put one packet into the jitter buffer */<br />
void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp);</p>
<p>/** Get one packet from the jitter buffer */<br />
void speex_jitter_get(SpeexJitter *jitter, spx_int16_t *out, int *start_offset);</p>
<p>/** Get pointer timestamp of jitter buffer */<br />
int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter);</p>
<p>#ifdef __cplusplus<br />
}<br />
#endif<br />
#define SAMPLING_RATE 16000<br />
#define FRAME_SIZE 320<br />
////////////////////////////////////////////////////////////////////</p>
<p>class SanSpeexEnc<br />
{<br />
public:<br />
    SanSpeexEnc();<br />
    ~SanSpeexEnc();</p>
<p>    /**<br />
     * @return 4 + 4 + encodedLen<br />
     * @rawin  must be 320 length<br />
     *  4+encodedLen &#124;   timestamp  &#124; encodedBuf<br />
     * &#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;<br />
     *  4            &#124;   4          &#124; encodedLen<br />
     */<br />
    int encode(const short *rawin, char *encodedBufOutWithTimestampAndLen);</p>
<p>    int playbackEcho(const short *rawin, bool ok); //TODO: remember to sync</p>
<p>    void captureEcho(short *rawin);<br />
    void captureEcho(short *rawin, short *playback);</p>
<p>private:<br />
    SpeexPreprocessState *preprocess;<br />
    void                 *enc_state;<br />
    SpeexBits             enc_bits;<br />
    int                   send_timestamp;<br />
    short                 pcm[FRAME_SIZE], pcm2[FRAME_SIZE];<br />
    SpeexEchoState       *echo_state;<br />
    char                  encodedBuf[FRAME_SIZE*2];</p>
<p>};<br />
class SanSpeexDec<br />
{<br />
public:<br />
    SanSpeexDec();<br />
    ~SanSpeexDec();</p>
<p>    void setSanSpeexEnc(SanSpeexEnc *ptr);<br />
    int put(const char *encodedBufWithTimestamp, int encodedLenWithTimestamp);<br />
    int get(short *rawout);<br />
    int afterPlayback(short *rawin, bool ok);</p>
<p>private:<br />
   void               *dec_state;<br />
   SpeexBits           dec_bits;<br />
   short               pcm[FRAME_SIZE];<br />
   SanSpeexEnc        *speexenc;<br />
   SpeexJitter         jitter;<br />
   int                 mostUpdatedTSatPut;<br />
   bool                firsttimecalling_get;</p>
<p>};</p>
<p>/////////////////////////////////////////////////////////////////////</p>
<p>&#160;</p>
<p>#endif // _SAN_SPEEX_H_</p>
<p>Speex source file:<br />
#include &#60;stdio.h&#62;<br />
#include &#60;limits.h&#62;<br />
#include &#8220;san_speex.h&#8221;<br />
#ifndef NULL<br />
#define NULL 0<br />
#endif<br />
#define ENABLE_AEC<br />
#ifdef ENABLE_AEC<br />
 #define USE_AEC_CAPTURE          /* will print a lot of speex warning */<br />
#endif</p>
<p>#include &#60;qglobal.h&#62;<br />
//#define NEED_DUMP<br />
#include &#60;stdio.h&#62;<br />
FILE *file = 0;<br />
char msg[128];<br />
void debugPrint(const char *msg)<br />
{<br />
#ifdef NEED_DUMP<br />
    if (file == 0)<br />
        file = fopen(&#8220;dump.txt&#8221;, &#8220;a&#8221;);<br />
    fprintf(file, msg);<br />
#endif<br />
}</p>
<p>void closeDebugPrint()<br />
{<br />
#ifdef NEED_DUMP<br />
    if (file)<br />
        fclose(file);<br />
    file = 0;<br />
#endif<br />
}</p>
<p>#define ECHOTAILSIZE  25<br />
short psSpeaker[320 * ECHOTAILSIZE * 10];<br />
void speex_jitter_init(SpeexJitter *jitter, void *decoder, int sampling_rate)<br />
{<br />
   jitter-&#62;dec = decoder;<br />
   speex_decoder_ctl(decoder, SPEEX_GET_FRAME_SIZE, &#38;jitter-&#62;frame_size);</p>
<p>   jitter-&#62;packets = jitter_buffer_init(jitter-&#62;frame_size);</p>
<p>   speex_bits_init(&#38;jitter-&#62;current_packet);<br />
   jitter-&#62;valid_bits = 0;<br />
}</p>
<p>void speex_jitter_destroy(SpeexJitter *jitter)<br />
{<br />
   jitter_buffer_destroy(jitter-&#62;packets);<br />
   speex_bits_destroy(&#38;jitter-&#62;current_packet);<br />
}</p>
<p>void speex_jitter_put(SpeexJitter *jitter, char *packet, int len, int timestamp)<br />
{<br />
   JitterBufferPacket p;<br />
   p.data = packet;<br />
   p.len = len;<br />
   p.timestamp = timestamp;<br />
   p.span = jitter-&#62;frame_size;<br />
   jitter_buffer_put(jitter-&#62;packets, &#38;p);<br />
   sprintf(msg, &#8220;put %d\n&#8221;, timestamp);<br />
   debugPrint(msg);<br />
}</p>
<p>void speex_jitter_get(SpeexJitter *jitter, spx_int16_t *out, int *current_timestamp)<br />
{<br />
   int i;<br />
   int ret;<br />
   spx_int32_t activity;<br />
   int bufferCount = 0;<br />
   JitterBufferPacket packet;<br />
   //char data[40960];<br />
   //packet.data = data;<br />
   //packet.len = 40960;<br />
   packet.data = reinterpret_cast&#60;char *&#62;(psSpeaker);<br />
   packet.len = 320 * ECHOTAILSIZE * 10;<br />
  <br />
   if (jitter-&#62;valid_bits)<br />
   {<br />
      /* Try decoding last received packet */<br />
      ret = speex_decode_int(jitter-&#62;dec, &#38;jitter-&#62;current_packet, out);<br />
      if (ret == 0)<br />
      {<br />
         jitter_buffer_tick(jitter-&#62;packets);<br />
         return;<br />
      } else {<br />
         jitter-&#62;valid_bits = 0;<br />
      }<br />
   }</p>
<p>   if (current_timestamp)<br />
    ret = jitter_buffer_get(jitter-&#62;packets, &#38;packet, jitter-&#62;frame_size, current_timestamp);<br />
   else<br />
    ret = jitter_buffer_get(jitter-&#62;packets, &#38;packet, jitter-&#62;frame_size, NULL);<br />
  <br />
   if (ret != JITTER_BUFFER_OK)<br />
   {<br />
      /* No packet found */<br />
      speex_decode_int(jitter-&#62;dec, NULL, out);<br />
   } else {<br />
      speex_bits_read_from(&#38;jitter-&#62;current_packet, packet.data, packet.len);<br />
      /* Decode packet */<br />
      ret = speex_decode_int(jitter-&#62;dec, &#38;jitter-&#62;current_packet, out);<br />
      if (ret == 0)<br />
      {<br />
         jitter-&#62;valid_bits = 1;<br />
      } else {<br />
         /* Error while decoding */<br />
         for (i=0;i&#60;jitter-&#62;frame_size;i++)<br />
            out[i]=0;<br />
      }<br />
   }<br />
   speex_decoder_ctl(jitter-&#62;dec, SPEEX_GET_ACTIVITY, &#38;activity);<br />
   if (activity &#60; 30)<br />
   {<br />
      jitter_buffer_update_delay(jitter-&#62;packets, &#38;packet, NULL);<br />
   }<br />
   jitter_buffer_tick(jitter-&#62;packets);<br />
   //ret = jitter_buffer_ctl(jitter-&#62;packets, JITTER_BUFFER_GET_AVALIABLE_COUNT, &#38;bufferCount);<br />
   //sprintf(msg, &#8220;   get %d bufferCount=%d\n&#8221;, speex_jitter_get_pointer_timestamp(jitter), bufferCount);<br />
   //debugPrint(msg);<br />
}</p>
<p>int speex_jitter_get_pointer_timestamp(SpeexJitter *jitter)<br />
{<br />
   return jitter_buffer_get_pointer_timestamp(jitter-&#62;packets);<br />
}<br />
//===========================================================<br />
SanSpeexEnc::SanSpeexEnc()<br />
            :preprocess(0),<br />
             enc_state(0),<br />
             enc_bits(),<br />
             send_timestamp(0),<br />
             echo_state(0)<br />
{<br />
    for (int i=0; i&#60;FRAME_SIZE; i++)<br />
        pcm[i] = 0;</p>
<p>    int tmp;<br />
    float tmpf;</p>
<p>    enc_state = speex_encoder_init(&#38;speex_wb_mode);<br />
    tmp = 3; //3,4,7,8,9,10 are not working<br />
    speex_encoder_ctl(enc_state, SPEEX_SET_QUALITY, &#38;tmp);<br />
    tmp = 7;<br />
    speex_encoder_ctl(enc_state, SPEEX_SET_COMPLEXITY, &#38;tmp);<br />
    speex_bits_init(&#38;enc_bits);</p>
<p>    echo_state = speex_echo_state_init(FRAME_SIZE, ECHOTAILSIZE*FRAME_SIZE);<br />
    tmp = SAMPLING_RATE;<br />
    speex_echo_ctl(echo_state, SPEEX_ECHO_SET_SAMPLING_RATE, &#38;tmp);</p>
<p>    preprocess = speex_preprocess_state_init(FRAME_SIZE, SAMPLING_RATE);<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_ECHO_STATE, echo_state);</p>
<p>    tmp = 1;<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DENOISE, &#38;tmp);<br />
    tmp = 0;<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC, &#38;tmp);<br />
    tmp = 1;<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_VAD, &#38;tmp);</p>
<p>    tmp = 0;<br />
 speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DEREVERB, &#38;tmp);<br />
    tmpf = 0.0;<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DEREVERB_DECAY, &#38;tmpf);<br />
    tmpf = 0.0;<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_DEREVERB_LEVEL, &#38;tmpf);</p>
<p>    tmp = 8000;//30000;<br />
    //speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC_TARGET, &#38;tmp);<br />
    tmp = 8000;<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC_LEVEL, &#38;tmp);<br />
    tmp = 5;<br />
    //speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_AGC_MAX_GAIN, &#38;tmp);<br />
    tmp = -30;<br />
    speex_preprocess_ctl(preprocess, SPEEX_PREPROCESS_SET_NOISE_SUPPRESS, &#38;tmp);<br />
}</p>
<p>SanSpeexEnc::~SanSpeexEnc()<br />
{<br />
    speex_encoder_destroy(enc_state); //&#8211;Destroy the encoder state<br />
    speex_echo_state_destroy(echo_state);<br />
    speex_preprocess_state_destroy(preprocess);<br />
    speex_bits_destroy(&#38;enc_bits); //&#8211;Destroy the bit-packing struct<br />
    closeDebugPrint();<br />
}</p>
<p>/**<br />
 * @return 4 + 4 + encodedLen<br />
 * @rawin  must be 320 length<br />
 *  4+encodedLen &#124;   timestamp  &#124; encodedBuf<br />
 * &#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8211;<br />
 *  4            &#124;   4          &#124; encodedLen<br />
 */<br />
int SanSpeexEnc::encode(const short *rawin, char *encodedBufOutWithTimestampAndLen)<br />
{<br />
#ifdef ENABLE_AEC<br />
    /* Perform echo cancellation */<br />
   #ifdef USE_AEC_CAPTURE<br />
    speex_echo_capture(echo_state, rawin, pcm2);<br />
   #else<br />
    speex_echo_cancellation(echo_state, rawin, psSpeaker, pcm2);<br />
   #endif<br />
    for (int i=0;i&#60;FRAME_SIZE;i++)<br />
        pcm[i] = pcm2[i];<br />
#else<br />
    for (int i=0;i&#60;FRAME_SIZE;i++)<br />
        pcm[i] = rawin[i];<br />
#endif</p>
<p>    speex_bits_reset(&#38;enc_bits);</p>
<p>    /* Apply noise/echo suppression */<br />
    bool isSpeech = speex_preprocess_run(preprocess, pcm);<br />
    /* Encode */<br />
    int needTransmit = speex_encode_int(enc_state, pcm, &#38;enc_bits);<br />
    int packetSize = 0;<br />
    if (isSpeech &#38;&#38; needTransmit)<br />
    {<br />
        packetSize = speex_bits_write(&#38;enc_bits, encodedBufOutWithTimestampAndLen+8, FRAME_SIZE*2);<br />
        <br />
        ((int*)encodedBufOutWithTimestampAndLen)[0] = packetSize+4;<br />
        ((int*)encodedBufOutWithTimestampAndLen)[1] = send_timestamp;<br />
        qDebug(&#8220;packetSize=%d, timestamp=%d&#8221;, packetSize, send_timestamp);<br />
    }</p>
<p>    send_timestamp += FRAME_SIZE;</p>
<p>    if (send_timestamp &#62;= INT_MAX)<br />
        send_timestamp = 0;</p>
<p>    if (packetSize &#62; 0)<br />
        return packetSize+4+4;<br />
    else<br />
        return 0;<br />
}</p>
<p>int SanSpeexEnc::playbackEcho(const short *rawin, bool ok)<br />
{<br />
#ifdef ENABLE_AEC<br />
    //TODO : sync<br />
    /* Put frame into playback buffer */<br />
   #ifdef USE_AEC_CAPTURE<br />
    if (!ok)<br />
        speex_echo_state_reset(echo_state);<br />
    speex_echo_playback(echo_state, rawin);<br />
   #endif<br />
#endif<br />
    return 1;<br />
}</p>
<p>void SanSpeexEnc::captureEcho(short *rawin)<br />
{<br />
#ifdef ENABLE_AEC<br />
   #ifdef USE_AEC_CAPTURE<br />
    speex_echo_capture(echo_state, rawin, pcm2);<br />
    for (int i=0; i&#60;FRAME_SIZE; i++)<br />
        rawin[i] = pcm2[i];</p>
<p>    speex_bits_reset(&#38;enc_bits);<br />
    speex_preprocess_run(preprocess, rawin);<br />
   #endif<br />
#endif<br />
}</p>
<p>void SanSpeexEnc::captureEcho(short *rawin, short *playback)<br />
{<br />
#ifdef ENABLE_AEC<br />
    speex_echo_cancellation(echo_state, rawin, playback, pcm2);<br />
    speex_preprocess_run(preprocess, pcm2);<br />
    for (int i=0; i&#60;FRAME_SIZE; i++)<br />
        rawin[i] = pcm2[i];<br />
#endif<br />
}</p>
<p>//==================================================<br />
SanSpeexDec::SanSpeexDec()<br />
            :dec_state(0),<br />
             dec_bits(),<br />
             speexenc(0),<br />
             jitter(),<br />
             mostUpdatedTSatPut(0),<br />
             firsttimecalling_get(true)<br />
{<br />
    for (int i=0; i&#60;FRAME_SIZE; i++)<br />
        pcm[i] = 0;<br />
    int tmp;</p>
<p>    dec_state = speex_decoder_init(&#38;speex_wb_mode);<br />
    tmp = 1;<br />
    speex_decoder_ctl(dec_state, SPEEX_SET_ENH, &#38;tmp);<br />
    speex_bits_init(&#38;dec_bits);<br />
    speex_jitter_init(&#38;jitter, dec_state, SAMPLING_RATE);<br />
}</p>
<p>SanSpeexDec::~SanSpeexDec()<br />
{<br />
    speex_jitter_destroy(&#38;jitter);</p>
<p>    //&#8211;Destroy the decoder state<br />
    speex_decoder_destroy(dec_state);</p>
<p>    //&#8211;Destroy the bit-stream truct<br />
    speex_bits_destroy(&#38;dec_bits);<br />
}</p>
<p>void SanSpeexDec::setSanSpeexEnc(SanSpeexEnc *ptr)<br />
{<br />
    speexenc = ptr;<br />
}</p>
<p>int SanSpeexDec::put(const char *encodedBufWithTimestamp, int encodedLenWithTimestamp)<br />
{<br />
    //buffer:<br />
    //  timestamp &#124; encodedBuf<br />
    // &#8212;&#8212;&#8212;&#8211;+&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;<br />
    //   4        &#124; encodedLenWithTimestamp &#8211; 4<br />
    int success = 0;<br />
    int recv_timestamp = ((int*)encodedBufWithTimestamp)[0];<br />
    mostUpdatedTSatPut = recv_timestamp;<br />
    if (firsttimecalling_get)<br />
        return 1;<br />
    speex_jitter_put(&#38;jitter, (char *)encodedBufWithTimestamp+4, encodedLenWithTimestamp-4, recv_timestamp);<br />
    return 1;<br />
}</p>
<p>int SanSpeexDec::get(short *rawout)<br />
{<br />
    if (firsttimecalling_get)<br />
    {<br />
        int ts = mostUpdatedTSatPut;<br />
        sprintf(msg, &#8220;MostUpdatedTSatPut = %d\n&#8221;, ts);<br />
        debugPrint(msg);<br />
        firsttimecalling_get = false;<br />
        speex_jitter_get(&#38;jitter, rawout, &#38;ts);<br />
    }<br />
    else<br />
        speex_jitter_get(&#38;jitter, rawout, 0);<br />
    return 1;<br />
}</p>
<p>int SanSpeexDec::afterPlayback(short *rawin, bool ok)<br />
{<br />
    if (speexenc)<br />
        return speexenc-&#62;playbackEcho(rawin, ok);<br />
    return 0;<br />
}</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Testing portaudio and speex - part 2]]></title>
<link>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-2/</link>
<pubDate>Wed, 11 Nov 2009 00:32:56 +0000</pubDate>
<dc:creator>slworkthings</dc:creator>
<guid>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-2/</guid>
<description><![CDATA[Continue. AudioClient header file: #include &#8220;mysocket.h&#8221; //=============================]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Continue.</p>
<p>AudioClient header file:<br />
#include &#8220;mysocket.h&#8221;</p>
<p>//==============================================================<br />
MySocket::MySocket(const QString&#38; myId)<br />
         :m_socketdevice(0),<br />
          m_running(false),<br />
          m_amIClient(true),<br />
          m_buf(0),<br />
          m_bufLen(1024),<br />
          m_myId(myId)<br />
{<br />
    m_socketdevice = new QSocketDevice();<br />
    m_socketdevice-&#62;setAddressReusable(true);<br />
    m_socketdevice-&#62;setBlocking(true);</p>
<p>    m_buf = new char[m_bufLen];<br />
}</p>
<p>MySocket::~MySocket()<br />
{<br />
    stop();</p>
<p>    delete m_socketdevice;<br />
    m_socketdevice = 0;</p>
<p>    delete [] m_buf;<br />
    m_buf = 0;<br />
}</p>
<p>void MySocket::setId(const QString&#38; id)<br />
{<br />
    m_myId = id;<br />
}</p>
<p>void MySocket::stop()<br />
{<br />
    if (m_running)<br />
    {<br />
        m_running = false;<br />
    }<br />
    if (m_socketdevice)<br />
        m_socketdevice-&#62;close();<br />
    //wait(500);<br />
    qDebug(&#8220;MySocket::stop&#8221;);<br />
}</p>
<p>bool MySocket::connectTo(const QString&#38; serverAddr, int port)<br />
{<br />
    m_amIClient = true;<br />
    if (!m_socketdevice)<br />
        return false;</p>
<p>    bool ok = m_socketdevice-&#62;connect(serverAddr, port);<br />
    wait(1000);<br />
    if (ok)<br />
    {<br />
        QString handshake = &#8220;myid=&#8221; + m_myId;<br />
        send(handshake);<br />
    }<br />
    return ok;<br />
}</p>
<p>void MySocket::setSocket(int socket)<br />
{<br />
    m_amIClient = false;<br />
    m_socketdevice-&#62;setSocket(socket, QSocketDevice::Stream);<br />
}</p>
<p>bool MySocket::hasError()<br />
{<br />
    if (!m_socketdevice)<br />
        return true;<br />
    return (m_socketdevice-&#62;error() != QSocketDevice::NoError);<br />
}</p>
<p>void MySocket::run()<br />
{<br />
    m_running = true;</p>
<p>    if (m_socketdevice)<br />
    {<br />
        qDebug(&#8220;port/peerPort = %d,%d&#8221;, m_socketdevice-&#62;port(), m_socketdevice-&#62;peerPort());<br />
    }</p>
<p>    int len = 0;<br />
    int readLen = 0;<br />
    while (m_running &#38;&#38; m_socketdevice &#38;&#38; !hasError())<br />
    {<br />
        len = m_socketdevice-&#62;bytesAvailable();<br />
        if (len &#62; 0)<br />
        {<br />
            if (len &#62; m_bufLen)<br />
            {<br />
                m_bufLen = len;<br />
                delete [] m_buf;<br />
                m_buf = new char[m_bufLen];<br />
            }</p>
<p>            readLen = m_socketdevice-&#62;readBlock(m_buf, len);<br />
            if (readLen &#60;= 0) //error<br />
            {<br />
                qDebug(&#8220;&#8212;&#8211; read error &#8212; 1&#8243;);<br />
                m_running = false;<br />
                break;<br />
            }<br />
            while (readLen &#60; len &#38;&#38; !hasError())<br />
            {<br />
                int curLen = m_socketdevice-&#62;readBlock(m_buf + readLen, len &#8211; readLen);<br />
                if (curLen &#60;= 0) //error<br />
                {<br />
                    qDebug(&#8220;&#8212;&#8211; read error &#8212; 3&#8243;);<br />
                    m_running = false;<br />
                    break;<br />
                }<br />
                readLen += curLen;<br />
            }<br />
            if (!m_running)<br />
                break;</p>
<p>            QByteArray ba(len);<br />
            const char *data = ba.data();<br />
            memcpy(ba.data(), m_buf, len);<br />
            if (len &#62; 5 &#38;&#38; data[0] == &#8216;m&#8217; &#38;&#38; data[1] == &#8216;y&#8217; &#38;&#38; data[2] == &#8216;i&#8217; &#38;&#38; data[3] == &#8216;d&#8217; &#38;&#38; data[4] == &#8216;=&#8217;)<br />
            {<br />
                QString handshake(ba);<br />
                QString hisId = handshake.mid(5);<br />
                emit fireReceivedHandshake(m_socketdevice-&#62;socket(), hisId);<br />
            }<br />
            else if (len &#62; 3 &#38;&#38; data[0] == &#8216;c&#8217; &#38;&#38; data[1] == &#8216;m&#8217; &#38;&#38; data[2] == &#8216;d&#8217; &#38;&#38; data[3] == &#8216;Q&#8217;)<br />
            {<br />
                m_running = false;<br />
                qDebug(&#8220;MySocket::run() got cmdQ&#8221;);<br />
                emit fireReceivedData(ba);<br />
            }<br />
            else<br />
                emit fireReceivedData(ba);<br />
        }<br />
        else<br />
        {<br />
            len = m_socketdevice-&#62;waitForMore(100);<br />
            if (len == -1 &#124;&#124; hasError()) //error<br />
            {<br />
                qDebug(&#8220;&#8212;&#8211; read error &#8212; 2&#8243;);<br />
                m_running = false;<br />
                break;<br />
            }<br />
        }<br />
    }//while()<br />
    qDebug(&#8220;&#8212;&#8211; done MySocket::run() &#8212;-&#8221;);<br />
}//run()</p>
<p>bool MySocket::send(const QByteArray&#38; ba)<br />
{<br />
    bool success = false;<br />
    if (!m_socketdevice)<br />
        return success;</p>
<p>    const char *data = ba.data();<br />
    int len = ba.size();<br />
    int writtenLen = 0;</p>
<p>   <br />
    writtenLen = m_socketdevice-&#62;writeBlock(data, len);<br />
    while (writtenLen &#60; len)<br />
    {<br />
        writtenLen += m_socketdevice-&#62;writeBlock(data + writtenLen, len &#8211; writtenLen);<br />
    }</p>
<p>    return (writtenLen == len);<br />
}</p>
<p>bool MySocket::send(const QString&#38; str)<br />
{<br />
    QCString cstr = str.utf8();<br />
    const char *data = (const char *)(cstr);<br />
    QByteArray ba(cstr.length());<br />
    memcpy(ba.data(), data, cstr.length());</p>
<p>    return send(ba);<br />
}<br />
//=====================================================<br />
MyServerSocket::MyServerSocket(Q_UINT16 port)<br />
               :QServerSocket(port),<br />
                m_mysocketDict(), //key=socket(int)<br />
                m_map() //socket(int), id(Qstring)<br />
{<br />
    m_mysocketDict.setAutoDelete(true);<br />
}</p>
<p>MyServerSocket::~MyServerSocket()<br />
{<br />
    m_mysocketDict.clear();<br />
    m_map.clear();<br />
}</p>
<p>void MyServerSocket::newConnection(int socket)<br />
{<br />
    MySocket *mysocket = new MySocket();<br />
    connect(mysocket, SIGNAL(fireReceivedData(const QByteArray&#38;)),<br />
                      SIGNAL(fireReceivedData(const QByteArray&#38;)));<br />
    connect(mysocket, SIGNAL(fireReceivedHandshake(int, const QString&#38;)),<br />
                      SLOT(slotReceivedHandshake(int, const QString&#38;)));<br />
    m_map.insert(socket, QString(&#8220;&#8221;));<br />
    m_mysocketDict.insert(QString::number(socket), mysocket);<br />
    mysocket-&#62;setSocket(socket);<br />
    mysocket-&#62;start();<br />
}</p>
<p>bool MyServerSocket::send(const QByteArray&#38; ba, const QString&#38; _id)<br />
{<br />
    QMap&#60;int, QString&#62;::Iterator it;<br />
    for (it = m_map.begin(); it != m_map.end(); ++it)<br />
    {<br />
        int key = it.key();<br />
        QString id = it.data();<br />
        if (id == _id) //found it<br />
        {<br />
            MySocket *sock = m_mysocketDict.find(QString::number(key));<br />
            if (sock)<br />
            {<br />
                return sock-&#62;send(ba);<br />
            }<br />
        }<br />
    }<br />
    return false;<br />
}</p>
<p>bool MyServerSocket::send(const QString&#38; str, const QString&#38; _id)<br />
{<br />
    QMap&#60;int, QString&#62;::Iterator it;<br />
    for (it = m_map.begin(); it != m_map.end(); ++it)<br />
    {<br />
        int key = it.key();<br />
        QString id = it.data();<br />
        if (id == _id) //found it<br />
        {<br />
            MySocket *sock = m_mysocketDict.find(QString::number(key));<br />
            if (sock)<br />
            {<br />
                return sock-&#62;send(str);<br />
            }<br />
        }<br />
    }<br />
    return false;<br />
}</p>
<p>void MyServerSocket::stop()<br />
{<br />
    QDictIterator&#60;MySocket&#62; it(m_mysocketDict);<br />
    MySocket *sock = 0;<br />
    for ( ; (sock = it.current()); ++it)<br />
    {<br />
        sock-&#62;stop();<br />
    }<br />
}</p>
<p>void MyServerSocket::slotReceivedHandshake(int socket, const QString&#38; hisId)<br />
{<br />
    qDebug(&#8220;&#8212;- receive handshake :&#8221; + QString::number(socket) + &#8221; =&#8221; + hisId);<br />
    m_map.insert(socket, hisId, true);<br />
    MySocket *sock = m_mysocketDict.find(QString::number(socket));<br />
    if (sock)<br />
    {<br />
        sock-&#62;setId(hisId);<br />
        emit fireReceivedHandshake(hisId);<br />
    }<br />
}</p>
<p> AudioClient source file:</p>
<p>#include &#8220;audioclient.h&#8221;<br />
#include &#60;qpushbutton.h&#62;<br />
#include &#60;qlabel.h&#62;<br />
#include &#60;qlayout.h&#62;<br />
#include &#60;qlineedit.h&#62;<br />
#include &#60;qapplication.h&#62;</p>
<p>//===================================<br />
AudioClient::AudioClient(int serverPort, bool isRecorder)<br />
            :QWidget(),<br />
             m_socket(0),<br />
             m_setBtn(0),<br />
             m_startBtn(0),<br />
             m_stopBtn(0),<br />
             m_edit(0),<br />
             m_isRecorder(isRecorder)<br />
{<br />
    m_socket = new MySocket(isRecorder ? &#8220;recorder&#8221; : &#8220;playback&#8221;);<br />
    connect(m_socket, SIGNAL(fireReceivedData(const QByteArray&#38;)),<br />
                      SLOT(slotReceivedData(const QByteArray&#38;)));</p>
<p>    QVBoxLayout *vlayout = new QVBoxLayout(this);</p>
<p>    QHBoxLayout *h1 = new QHBoxLayout(0);<br />
    QLabel *label1 = new QLabel(&#8220;Set Device Index:&#8221;, this);<br />
    m_edit = new QLineEdit(this);<br />
    m_edit-&#62;setText(isRecorder ? &#8220;1&#8243; : &#8220;7&#8243;);<br />
    m_setBtn = new QPushButton(isRecorder ? &#8220;Set Capture Dev&#8221; : &#8220;Set Playback Dev&#8221;, this);<br />
    h1-&#62;addWidget(label1);<br />
    h1-&#62;addWidget(m_edit);<br />
    h1-&#62;addWidget(m_setBtn);<br />
    vlayout-&#62;addItem(h1);</p>
<p>    QHBoxLayout *h2 = new QHBoxLayout(0);<br />
    QLabel *label2 = new QLabel(isRecorder ? &#8220;Start Capture&#8221; : &#8220;Start Playback&#8221;, this);<br />
    m_startBtn = new QPushButton(&#8220;Start&#8221;, this);<br />
    h2-&#62;addWidget(label2);<br />
    h2-&#62;addWidget(m_startBtn);<br />
    vlayout-&#62;addItem(h2);</p>
<p>    QHBoxLayout *h3 = new QHBoxLayout(0);<br />
    QLabel *label3 = new QLabel(isRecorder ? &#8220;Stop Capture&#8221; : &#8220;Stop Playback&#8221;, this);<br />
    m_stopBtn = new QPushButton(&#8220;Stop&#8221;, this);<br />
    h3-&#62;addWidget(label3);<br />
    h3-&#62;addWidget(m_stopBtn);<br />
    vlayout-&#62;addItem(h3);</p>
<p>    QPushButton *exitBtn = new QPushButton(&#8220;Exit&#8221;, this);<br />
    vlayout-&#62;addWidget(exitBtn);</p>
<p>    connect(m_setBtn,   SIGNAL(clicked()), SLOT(slotSetClicked()));<br />
    connect(m_startBtn, SIGNAL(clicked()), SLOT(slotStartClicked()));<br />
    connect(m_stopBtn,  SIGNAL(clicked()), SLOT(slotStopClicked()));<br />
    connect(exitBtn,    SIGNAL(clicked()), SLOT(slotExitClicked()));</p>
<p>    move(isRecorder ? 30 : 130, isRecorder ? 30 : 130);<br />
    setCaption(isRecorder ? &#8220;RecorderClient&#8221; : &#8220;PlaybackClient&#8221;);</p>
<p>    bool ok = m_socket-&#62;connectTo(&#8220;127.0.0.1&#8243;, serverPort);<br />
    qDebug(&#8220;connect to = %d&#8221;, ok);<br />
    if (ok)<br />
        m_socket-&#62;start();<br />
}</p>
<p>AudioClient::~AudioClient()<br />
{<br />
    delete m_socket;<br />
    m_socket = 0;<br />
}</p>
<p>void AudioClient::slotSetClicked()<br />
{<br />
    QString str = m_isRecorder ? &#8220;cmd2&#8243; : &#8220;cmd3&#8243;;<br />
    str += m_edit-&#62;text().stripWhiteSpace();<br />
    m_socket-&#62;send(str);<br />
    m_setBtn-&#62;setEnabled(false);<br />
}</p>
<p>void AudioClient::slotStartClicked()<br />
{<br />
    m_socket-&#62;send(m_isRecorder ? &#8220;cmd4&#8243; : &#8220;cmd5&#8243;);<br />
    m_startBtn-&#62;setEnabled(false);<br />
}</p>
<p>void AudioClient::slotStopClicked()<br />
{<br />
    m_socket-&#62;send(m_isRecorder ? &#8220;cmd6&#8243; : &#8220;cmd7&#8243;);<br />
    m_stopBtn-&#62;setEnabled(false);<br />
}</p>
<p>void AudioClient::slotExitClicked()<br />
{<br />
    if (m_socket &#38;&#38; m_socket-&#62;isValid())<br />
    {<br />
        m_socket-&#62;send(&#8220;cmdQ&#8221;);<br />
        m_socket-&#62;stop();<br />
    }<br />
    close();<br />
    qApp-&#62;quit();<br />
}</p>
<p>void AudioClient::closeEvent(QCloseEvent *)<br />
{<br />
    if (m_socket &#38;&#38; m_socket-&#62;isValid())<br />
    {<br />
        m_socket-&#62;send(&#8220;cmdQ&#8221;);<br />
        m_socket-&#62;stop();<br />
    }<br />
    qApp-&#62;quit();<br />
}</p>
<p>void AudioClient::slotReceivedData(const QByteArray&#38; ba)<br />
{<br />
    const char *data = ba.data();<br />
    if (ba.size() &#62;= 4 &#38;&#38; data[0] == &#8216;c&#8217; &#38;&#38; data[1] == &#8216;m&#8217; &#38;&#38; data[2] == &#8216;d&#8217;)<br />
    {<br />
        char cmd = data[3];<br />
        switch (cmd)<br />
        {<br />
        case &#8216;1&#8242;: //return device list;   dev1\ndev2\n&#8230;<br />
            {<br />
                QString devList(ba);<br />
                devList = devList.mid(4);<br />
                qDebug(&#8220;1. DevList = &#8221; + devList);<br />
            }<br />
            break;<br />
        case &#8216;2&#8242;: //set recorder device;  devname<br />
            {<br />
                QString devName(ba);<br />
                devName = devName.mid(4);<br />
                qDebug(&#8220;2. RecorderDevice = &#8221; + devName);<br />
            }<br />
            break;<br />
        case &#8216;3&#8242;: //set playback device; devname<br />
            {<br />
                QString devName(ba);<br />
                devName = devName.mid(4);<br />
                qDebug(&#8220;3. PlaybackDevice = &#8221; + devName);<br />
            }<br />
            break;<br />
        case &#8216;4&#8242;: //start recorder<br />
            qDebug(&#8220;4. Start Recording&#8221;);<br />
            break;<br />
        case &#8216;5&#8242;: //start playback<br />
            qDebug(&#8220;5. Start Playback&#8221;);<br />
            break;<br />
        case &#8216;6&#8242;: //stop recorder<br />
            qDebug(&#8220;6. Stop Recording&#8221;);<br />
            break;<br />
        case &#8216;7&#8242;: //stop playback<br />
            qDebug(&#8220;7. Stop Playback&#8221;);<br />
            break;<br />
        case &#8216;Q&#8217;:<br />
            qDebug(&#8220;Q. Quit&#8221;);<br />
            slotExitClicked();<br />
            break;<br />
        default:<br />
            break;<br />
        }<br />
    }//cmd<br />
    else<br />
    {<br />
        if (ba.size() &#62; <img src='http://s.wordpress.com/wp-includes/images/smilies/icon_cool.gif' alt='8)' class='wp-smiley' /><br />
        {<br />
            const char *data = ba.data();<br />
            int packetSize = ((int*)data)[0];<br />
            int timestamp = ((int*)data)[1];<br />
            qDebug(&#8220;got packetSize=%d, timestamp=%d&#8221;, packetSize, timestamp);<br />
        }<br />
    }<br />
}//slotReceivedData()</p>
<p>&#160;</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Testing portaudio and speex - part 1]]></title>
<link>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-1/</link>
<pubDate>Wed, 11 Nov 2009 00:31:08 +0000</pubDate>
<dc:creator>slworkthings</dc:creator>
<guid>http://slworkthings.wordpress.com/2009/11/11/testing-portaudio-and-speex-part-1/</guid>
<description><![CDATA[This is a testing program I wrote in QT3 to test audio capture/playback loop in a local machine. Usi]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>This is a testing program I wrote in QT3 to test audio capture/playback loop in a local machine. Using 2 testing clients to communicate with AudioEngine which handling audio capturing/playing. Of course, need a lot of improvement on audio quality and AGC, AEC&#8230; ,etc.</p>
<p>socket header file:<br />
#ifndef _MYSOCKET_H_<br />
#define _MYSOCKET_H_</p>
<p>#include &#60;qsocketdevice.h&#62;<br />
#include &#60;qthread.h&#62;<br />
#include &#60;qobject.h&#62;<br />
#include &#60;qserversocket.h&#62;<br />
#include &#60;qdict.h&#62;<br />
#include &#60;qmap.h&#62;</p>
<p>//==============================================<br />
class MySocket : public QObject, public QThread<br />
{<br />
    Q_OBJECT<br />
public:<br />
    MySocket(const QString&#38; myId = QString::null);<br />
    ~MySocket();</p>
<p>    //I am client<br />
    bool connectTo(const QString&#38; serverAddr, int port);</p>
<p>    //I am server<br />
    void setSocket(int socket);<br />
    void setId(const QString&#38; id);</p>
<p>    bool send(const QByteArray&#38;);<br />
    bool send(const QString&#38; str);<br />
    void stop();</p>
<p>    bool isValid() { return (m_socketdevice &#38;&#38; m_socketdevice-&#62;isValid()); }</p>
<p>signals:<br />
    void fireReceivedData(const QByteArray&#38;);<br />
    void fireReceivedHandshake(int socket, const QString&#38;);</p>
<p>protected:<br />
    virtual void run();</p>
<p>private:<br />
    bool             hasError();</p>
<p>    QSocketDevice   *m_socketdevice;<br />
    bool             m_running;<br />
    bool             m_amIClient;<br />
    char            *m_buf;<br />
    int              m_bufLen;<br />
    QString          m_myId;<br />
};<br />
//=====================================================<br />
class MyServerSocket : public QServerSocket<br />
{<br />
    Q_OBJECT<br />
public:<br />
    MyServerSocket(Q_UINT16 port = 4242);<br />
    ~MyServerSocket();</p>
<p>    bool send(const QByteArray&#38;, const QString&#38; id);<br />
    bool send(const QString&#38;, const QString&#38; id);<br />
    void stop();</p>
<p>signals:<br />
    void fireReceivedData(const QByteArray&#38;);<br />
    void fireReceivedHandshake(const QString&#38; hisId);</p>
<p>private slots:<br />
    void slotReceivedHandshake(int socket, const QString&#38; hisId);</p>
<p>protected:<br />
    virtual void newConnection(int socket);</p>
<p>private:<br />
    QDict&#60;MySocket&#62;      m_mysocketDict; //key=socket(int)<br />
    QMap&#60;int, QString&#62;   m_map;<br />
};<br />
#endif // _MYSOCKET_H_</p>
<p>socket source file:<br />
#include &#8220;mysocket.h&#8221;</p>
<p>//==============================================================<br />
MySocket::MySocket(const QString&#38; myId)<br />
         :m_socketdevice(0),<br />
          m_running(false),<br />
          m_amIClient(true),<br />
          m_buf(0),<br />
          m_bufLen(1024),<br />
          m_myId(myId)<br />
{<br />
    m_socketdevice = new QSocketDevice();<br />
    m_socketdevice-&#62;setAddressReusable(true);<br />
    m_socketdevice-&#62;setBlocking(true);</p>
<p>    m_buf = new char[m_bufLen];<br />
}</p>
<p>MySocket::~MySocket()<br />
{<br />
    stop();</p>
<p>    delete m_socketdevice;<br />
    m_socketdevice = 0;</p>
<p>    delete [] m_buf;<br />
    m_buf = 0;<br />
}</p>
<p>void MySocket::setId(const QString&#38; id)<br />
{<br />
    m_myId = id;<br />
}</p>
<p>void MySocket::stop()<br />
{<br />
    if (m_running)<br />
    {<br />
        m_running = false;<br />
    }<br />
    if (m_socketdevice)<br />
        m_socketdevice-&#62;close();<br />
    //wait(500);<br />
    qDebug(&#8220;MySocket::stop&#8221;);<br />
}</p>
<p>bool MySocket::connectTo(const QString&#38; serverAddr, int port)<br />
{<br />
    m_amIClient = true;<br />
    if (!m_socketdevice)<br />
        return false;</p>
<p>    bool ok = m_socketdevice-&#62;connect(serverAddr, port);<br />
    wait(1000);<br />
    if (ok)<br />
    {<br />
        QString handshake = &#8220;myid=&#8221; + m_myId;<br />
        send(handshake);<br />
    }<br />
    return ok;<br />
}</p>
<p>void MySocket::setSocket(int socket)<br />
{<br />
    m_amIClient = false;<br />
    m_socketdevice-&#62;setSocket(socket, QSocketDevice::Stream);<br />
}</p>
<p>bool MySocket::hasError()<br />
{<br />
    if (!m_socketdevice)<br />
        return true;<br />
    return (m_socketdevice-&#62;error() != QSocketDevice::NoError);<br />
}</p>
<p>void MySocket::run()<br />
{<br />
    m_running = true;</p>
<p>    if (m_socketdevice)<br />
    {<br />
        qDebug(&#8220;port/peerPort = %d,%d&#8221;, m_socketdevice-&#62;port(), m_socketdevice-&#62;peerPort());<br />
    }</p>
<p>    int len = 0;<br />
    int readLen = 0;<br />
    while (m_running &#38;&#38; m_socketdevice &#38;&#38; !hasError())<br />
    {<br />
        len = m_socketdevice-&#62;bytesAvailable();<br />
        if (len &#62; 0)<br />
        {<br />
            if (len &#62; m_bufLen)<br />
            {<br />
                m_bufLen = len;<br />
                delete [] m_buf;<br />
                m_buf = new char[m_bufLen];<br />
            }</p>
<p>            readLen = m_socketdevice-&#62;readBlock(m_buf, len);<br />
            if (readLen &#60;= 0) //error<br />
            {<br />
                qDebug(&#8220;&#8212;&#8211; read error &#8212; 1&#8243;);<br />
                m_running = false;<br />
                break;<br />
            }<br />
            while (readLen &#60; len &#38;&#38; !hasError())<br />
            {<br />
                int curLen = m_socketdevice-&#62;readBlock(m_buf + readLen, len &#8211; readLen);<br />
                if (curLen &#60;= 0) //error<br />
                {<br />
                    qDebug(&#8220;&#8212;&#8211; read error &#8212; 3&#8243;);<br />
                    m_running = false;<br />
                    break;<br />
                }<br />
                readLen += curLen;<br />
            }<br />
            if (!m_running)<br />
                break;</p>
<p>            QByteArray ba(len);<br />
            const char *data = ba.data();<br />
            memcpy(ba.data(), m_buf, len);<br />
            if (len &#62; 5 &#38;&#38; data[0] == &#8216;m&#8217; &#38;&#38; data[1] == &#8216;y&#8217; &#38;&#38; data[2] == &#8216;i&#8217; &#38;&#38; data[3] == &#8216;d&#8217; &#38;&#38; data[4] == &#8216;=&#8217;)<br />
            {<br />
                QString handshake(ba);<br />
                QString hisId = handshake.mid(5);<br />
                emit fireReceivedHandshake(m_socketdevice-&#62;socket(), hisId);<br />
            }<br />
            else if (len &#62; 3 &#38;&#38; data[0] == &#8216;c&#8217; &#38;&#38; data[1] == &#8216;m&#8217; &#38;&#38; data[2] == &#8216;d&#8217; &#38;&#38; data[3] == &#8216;Q&#8217;)<br />
            {<br />
                m_running = false;<br />
                qDebug(&#8220;MySocket::run() got cmdQ&#8221;);<br />
                emit fireReceivedData(ba);<br />
            }<br />
            else<br />
                emit fireReceivedData(ba);<br />
        }<br />
        else<br />
        {<br />
            len = m_socketdevice-&#62;waitForMore(100);<br />
            if (len == -1 &#124;&#124; hasError()) //error<br />
            {<br />
                qDebug(&#8220;&#8212;&#8211; read error &#8212; 2&#8243;);<br />
                m_running = false;<br />
                break;<br />
            }<br />
        }<br />
    }//while()<br />
    qDebug(&#8220;&#8212;&#8211; done MySocket::run() &#8212;-&#8221;);<br />
}//run()</p>
<p>bool MySocket::send(const QByteArray&#38; ba)<br />
{<br />
    bool success = false;<br />
    if (!m_socketdevice)<br />
        return success;</p>
<p>    const char *data = ba.data();<br />
    int len = ba.size();<br />
    int writtenLen = 0;</p>
<p>   <br />
    writtenLen = m_socketdevice-&#62;writeBlock(data, len);<br />
    while (writtenLen &#60; len)<br />
    {<br />
        writtenLen += m_socketdevice-&#62;writeBlock(data + writtenLen, len &#8211; writtenLen);<br />
    }</p>
<p>    return (writtenLen == len);<br />
}</p>
<p>bool MySocket::send(const QString&#38; str)<br />
{<br />
    QCString cstr = str.utf8();<br />
    const char *data = (const char *)(cstr);<br />
    QByteArray ba(cstr.length());<br />
    memcpy(ba.data(), data, cstr.length());</p>
<p>    return send(ba);<br />
}<br />
//=====================================================<br />
MyServerSocket::MyServerSocket(Q_UINT16 port)<br />
               :QServerSocket(port),<br />
                m_mysocketDict(), //key=socket(int)<br />
                m_map() //socket(int), id(Qstring)<br />
{<br />
    m_mysocketDict.setAutoDelete(true);<br />
}</p>
<p>MyServerSocket::~MyServerSocket()<br />
{<br />
    m_mysocketDict.clear();<br />
    m_map.clear();<br />
}</p>
<p>void MyServerSocket::newConnection(int socket)<br />
{<br />
    MySocket *mysocket = new MySocket();<br />
    connect(mysocket, SIGNAL(fireReceivedData(const QByteArray&#38;)),<br />
                      SIGNAL(fireReceivedData(const QByteArray&#38;)));<br />
    connect(mysocket, SIGNAL(fireReceivedHandshake(int, const QString&#38;)),<br />
                      SLOT(slotReceivedHandshake(int, const QString&#38;)));<br />
    m_map.insert(socket, QString(&#8220;&#8221;));<br />
    m_mysocketDict.insert(QString::number(socket), mysocket);<br />
    mysocket-&#62;setSocket(socket);<br />
    mysocket-&#62;start();<br />
}</p>
<p>bool MyServerSocket::send(const QByteArray&#38; ba, const QString&#38; _id)<br />
{<br />
    QMap&#60;int, QString&#62;::Iterator it;<br />
    for (it = m_map.begin(); it != m_map.end(); ++it)<br />
    {<br />
        int key = it.key();<br />
        QString id = it.data();<br />
        if (id == _id) //found it<br />
        {<br />
            MySocket *sock = m_mysocketDict.find(QString::number(key));<br />
            if (sock)<br />
            {<br />
                return sock-&#62;send(ba);<br />
            }<br />
        }<br />
    }<br />
    return false;<br />
}</p>
<p>bool MyServerSocket::send(const QString&#38; str, const QString&#38; _id)<br />
{<br />
    QMap&#60;int, QString&#62;::Iterator it;<br />
    for (it = m_map.begin(); it != m_map.end(); ++it)<br />
    {<br />
        int key = it.key();<br />
        QString id = it.data();<br />
        if (id == _id) //found it<br />
        {<br />
            MySocket *sock = m_mysocketDict.find(QString::number(key));<br />
            if (sock)<br />
            {<br />
                return sock-&#62;send(str);<br />
            }<br />
        }<br />
    }<br />
    return false;<br />
}</p>
<p>void MyServerSocket::stop()<br />
{<br />
    QDictIterator&#60;MySocket&#62; it(m_mysocketDict);<br />
    MySocket *sock = 0;<br />
    for ( ; (sock = it.current()); ++it)<br />
    {<br />
        sock-&#62;stop();<br />
    }<br />
}</p>
<p>void MyServerSocket::slotReceivedHandshake(int socket, const QString&#38; hisId)<br />
{<br />
    qDebug(&#8220;&#8212;- receive handshake :&#8221; + QString::number(socket) + &#8221; =&#8221; + hisId);<br />
    m_map.insert(socket, hisId, true);<br />
    MySocket *sock = m_mysocketDict.find(QString::number(socket));<br />
    if (sock)<br />
    {<br />
        sock-&#62;setId(hisId);<br />
        emit fireReceivedHandshake(hisId);<br />
    }<br />
}</p>
<p>&#160;</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Art Lebedev's Rozetkus 3D Socket Cuts Down On Wires]]></title>
<link>http://range.wordpress.com/2009/11/10/art-lebedevs-rozetkus-3d-socket-cuts-down-on-wires/</link>
<pubDate>Tue, 10 Nov 2009 08:03:34 +0000</pubDate>
<dc:creator>range</dc:creator>
<guid>http://range.wordpress.com/2009/11/10/art-lebedevs-rozetkus-3d-socket-cuts-down-on-wires/</guid>
<description><![CDATA[Art Lebedev&#8217;s most recent project is a refresher on their Rozetkus power strip. What&#8217;s r]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><a href="http://www.unplggd.com/unplggd/how-to/art-lebedevs-rozetkus-3d-power-socket-cuts-down-on-wires-100879"><img src="http://www.unplggd.com/uimages/unplggd/110909_rg_rozetkus_01.jpg" alt="110909_rg_rozetkus_01.jpg" width="540" height="545" /></a>Art Lebedev&#8217;s most recent project is a refresher on their Rozetkus power strip. What&#8217;s really interesting is that it&#8217;s more than just a socket. It can deploy an additional 4 sockets from its midst. Funky enough for you?</p>
<p><a href="http://www.unplggd.com/unplggd/how-to/art-lebedevs-rozetkus-3d-power-socket-cuts-down-on-wires-100879">Read More&#8230;</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[setsockopt SO_LINGER]]></title>
<link>http://cotton5415.wordpress.com/2009/10/30/setsockopt-so_linger/</link>
<pubDate>Fri, 30 Oct 2009 02:51:16 +0000</pubDate>
<dc:creator>cotton5415</dc:creator>
<guid>http://cotton5415.wordpress.com/2009/10/30/setsockopt-so_linger/</guid>
<description><![CDATA[SO_LINGER: 只針對 socket 的 close() 發揮作用。 case 1 (default): linger-&gt;l_onoff = 0; &#8211;&gt; linger-]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>SO_LINGER:<br />
只針對 socket 的 close() 發揮作用。<br />
case 1 (default):<br />
    linger-&#62;l_onoff = 0; &#8211;&#62; linger-&#62;l_linger no effect;<br />
case 2:<br />
    linger-&#62;l_onoff !=0; linger-&#62;l_linger = 0 ;<br />
    close() immediately. 不管底層的資料是否送出，直接送一個 RST(reset)給另一端。因此另一端在 recv的時候，會產生 ECONNRESET 的 error</p>
<p>case 3:<br />
    linger-&#62;l_onff != 0; linger-&#62;l_linger != 0;<br />
    close() 會 block住或是等到 l_linger 的timeout時間到之後，產生 EWOULDBLOCK error </p>
<p>ref: http://www.developerweb.net/forum/archive/index.php/t-2982.html</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Cartas e Eventos. Comunicação entre módulos em C.]]></title>
<link>http://ohbit.wordpress.com/2009/10/28/cartas-e-eventos-comunicacao-entre-modulos-em-c/</link>
<pubDate>Wed, 28 Oct 2009 02:21:09 +0000</pubDate>
<dc:creator>guilhermealexs</dc:creator>
<guid>http://ohbit.wordpress.com/2009/10/28/cartas-e-eventos-comunicacao-entre-modulos-em-c/</guid>
<description><![CDATA[Bem que C poderia ser como Java, não é? Acabo de bater três vezes na madeira aqui ao lado. Mais uma ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>Bem que C poderia ser como Java, não é? Acabo de bater três vezes na madeira aqui ao lado. Mais uma para ter certeza. De qualquer maneira, pouco me importa C ou Java (só não aceito Delphi). O fato é que C obriga o programador a implementar por conta própria recursos que já são de base em outras linguagens. Sim, isso é lindo.</p>
<p>Vejam bem, estava implementando um servidor GPRS que precisava manter uma conexão TCP. Para isso, abri mão das threads e trabalhei assincronamente utilizando a função select (não é a mais eficiente, mas precisava ter um certa compatibilidade com UNIX). O problema de não usar threads é que isso tende a centralizar o código, forçando a utilização das mensagens trocadas onde se implementa a própria rede.</p>
<p>Bem, eis o que fiz para descentralizar o código. A coisa foi parecida com um esquema de eventos, mas com nomes diferentes. Tudo começa quando o módulo de rede (que roda numa thread) recebe mensagens. Essas mensagens são enfileiradas num formato específico, geralmente contendo a mensagem recebida e algum outro parâmetro, que então serão eventualmente lidas e retiradas da fila por algum outro módulo do sistema. Dando nome aos bois:</p>
<ul>
<li>Mensagens de rede (recebidas): Cartas</li>
<li>Fila de mensagens: Caixa Postal</li>
</ul>
<p>É isso. A vantagem disso tudo é que o código fica mais limpo, torna a separação em módulos mais bonita e natural.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[We have over 1,000 BGA footprints online. Search, select, and build a part number at www.bgasockets.com]]></title>
<link>http://advancedint.wordpress.com/2009/10/27/we-have-over-1000-bga-footprints-online-search-select-and-build-a-part-number-at-www-bgasockets-com/</link>
<pubDate>Tue, 27 Oct 2009 16:16:53 +0000</pubDate>
<dc:creator>Advanced Interconnections</dc:creator>
<guid>http://advancedint.wordpress.com/2009/10/27/we-have-over-1000-bga-footprints-online-search-select-and-build-a-part-number-at-www-bgasockets-com/</guid>
<description><![CDATA[One of over 1,000 BGA footprints available in our fully searchable online database. BGA Socket Finde]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><div id="attachment_49" class="wp-caption alignright" style="width: 182px"><a href="http://www.bgasockets.com"><img class="size-full wp-image-49  " title="BGA Footprint 84-9" src="http://advancedint.wordpress.com/files/2009/10/b84_9.jpg" alt="BGA Footprint 84-9" width="172" height="271" /></a><p class="wp-caption-text">One of over 1,000 BGA footprints available in our fully searchable online database.</p></div>
<p>BGA Socket Finder™ is an interactive database of over 1,000 Ball Grid Array footprints ranging in pitch from 0.50mm to 1.27mm. Engineers from around the world use this online database every day to search for their device footprints by pin count, pitch, package size, or row count. The more criteria you enter, the more refined your search results will be. Use the footprint number to build a part number for the exact BGA socket or adapter required for your application. Footprint-specific data sheets and CAD drawings available online. Access to the database is free with registration. Start your search at www.bgasockets.com.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[A multi-threaded socket-based server]]></title>
<link>http://cheetim.wordpress.com/2009/10/18/a-multi-threaded-socket-based-server/</link>
<pubDate>Sun, 18 Oct 2009 06:38:39 +0000</pubDate>
<dc:creator>cheetim</dc:creator>
<guid>http://cheetim.wordpress.com/2009/10/18/a-multi-threaded-socket-based-server/</guid>
<description><![CDATA[The problem is old &#8211; How to implement a multi-threaded, socket-based server that will let you ]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>The problem is old &#8211; How to implement a multi-threaded, socket-based server that will let you read and write to the client (for example a telnet terminal.</p>
<p>There are several problems with constructing such a server:</p>
<ol>
<li>You have to use threads because otherwise clients will be queued up waiting for a connection.</li>
<li>Many of the publicly available examples (even some in some books) do not work for I/O servers. They are mostly developed around reading from a socket not writing to the socket as well. In our example we give a working read/write code example.</li>
<li> You need to avoid race conditions when starting up a thread at times when connections are coming through thick and fast.</li>
</ol>
<p>The code below will implement just such a server. It is intended for a head start, so is a template rather than a tutorial on how to write a server in Java. We have decided on port 4444 to listen on in the example, but you need to decide on a suitable port yourself.</p>
<p>The server will run, establishing connections from the port and echoing input received until it receives a line of input that is a full stop only &#8220;.&#8221;.</p>
<p>The Kieser.net team.<br />
Honeypot: spam@kieser.net<br />
http://www.kieser.net/linux/java_server.html</p>
<pre class="brush: java;">

import java.io.*;
import java.net.*;

/**
 * Title:        Sample Server
 * Description:  This utility will accept input from a socket, posting back to the socket before closing the link.
 * It is intended as a template for coders to base servers on. Please report bugs to brad at kieser.net
 * Copyright:    Copyright (c) 2002
 * Company:      Kieser.net
 * @author B. Kieser
 * @version 1.0
 */
public class sample_server {

private static int port=4444, maxConnections=0;

// Listen for incoming connections and handle them

public static void main(String[] args) {

int i=0;

try{
ServerSocket listener = new ServerSocket(port);
Socket server;

while((i++ &#60; maxConnections) &#124;&#124; (maxConnections == 0)){
doComms connection;

server = listener.accept();
doComms conn_c= new doComms(server);
Thread t = new Thread(conn_c);
t.start();
}
} catch (IOException ioe) {
System.out.println(&#34;IOException on socket listen: &#34; + ioe);
ioe.printStackTrace();
}
}

}

class doComms implements Runnable {
 private Socket server;
 private String line,input;

 doComms(Socket server) {
 this.server=server;
 }

 public void run () {

 input=&#34;&#34;;

 try {
 // Get input from the client
 DataInputStream in = new DataInputStream (server.getInputStream());
 PrintStream out = new PrintStream(server.getOutputStream());

 while((line = in.readLine()) != null &#38;&#38; !line.equals(&#34;.&#34;)) {
 input=input + line;
 out.println(&#34;I got:&#34; + line);
 }

 // Now write to the client

 System.out.println(&#34;Overall message is:&#34; + input);
 out.println(&#34;Overall message is:&#34; + input);

 server.close();
 } catch (IOException ioe) {
 System.out.println(&#34;IOException on socket listen: &#34; + ioe);
 ioe.printStackTrace();
 }
 }
}
</pre>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Replacing the costly hand-loading of socket terminals with customizable Peel-A-Way® Removable Terminal Carriers just got easier. ]]></title>
<link>http://advancedint.wordpress.com/2009/10/13/replacing-the-costly-hand-loading-of-socket-terminals-with-customizable-peel-a-way%c2%ae-removable-terminal-carriers-just-got-easier/</link>
<pubDate>Tue, 13 Oct 2009 19:43:02 +0000</pubDate>
<dc:creator>Advanced Interconnections</dc:creator>
<guid>http://advancedint.wordpress.com/2009/10/13/replacing-the-costly-hand-loading-of-socket-terminals-with-customizable-peel-a-way%c2%ae-removable-terminal-carriers-just-got-easier/</guid>
<description><![CDATA[In addition to traditional single-, dual-, triple-row and grid array patterns, Advanced Interconnect]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>In addition to traditional single-, dual-, triple-row and grid array patterns, Advanced Interconnections Corp. now offers its extensive line of Peel-A-Way<sup>®</sup> removable terminal carriers in nonlinear configurations.</p>
<p>The RoHS-compliant polyimide film carriers can be ordered in a wide variety of shapes, patterns and pin spacing</p>
<div id="attachment_35" class="wp-caption alignright" style="width: 282px"><a href="http://www.advanced.com/peelstart.html"><img class="size-full wp-image-35" title="AIC_Circular_PAW_72dpi_272pix" src="http://advancedint.wordpress.com/files/2009/10/aic_circular_paw_72dpi_272pix.jpg" alt="Peel-A-Way Removable Terminal Carrier" width="272" height="176" /></a><p class="wp-caption-text">Peel-A-Way® Removable Terminal Carrier</p></div>
<p>to suit virtually any through-hole or press-fit application. Unique configurations with random pin patterns and multiple terminal styles on a single carrier can be quickly designed to meet application requirements. Cutouts can be included to provide for component clearance or heat dissipation.</p>
<p>Peel-A-Way carriers feature a lightweight, ultra-low-profile insulator (only .005&#8243; (0.13mm) thick), suitable for automated pick-and-place. Supplied with Advanced<sup>®</sup> screw-machined terminals for superior reliability, Peel-A-Way carriers can be easily removed after soldering for complete visibility or left in place for added stability. Multiple terminal styles can be loaded on a single carrier, saving time and eliminating the potential for error associated with hand-loading individual pins on PC boards. Standard and custom terminal styles are available in a variety of plating options. Standard socket terminals accept leads as small as .010&#8243; (.25mm) and as large as .102&#8243; (2.59mm) and are available with optional solder preforms, which eliminate the need for wave soldering in an SMT environment.<br />
Pricing and lead time vary based on terminal selection and quantity.</p>
<p>Advanced Interconnections Corporation is an ISO 9001 Certified designer and manufacturer of electronic interconnect solutions, with world headquarters located in Rhode Island (USA). For more information, visit www.advanced.com or contact Advanced Interconnections&#8217; customer service department at: 5 Energy Way, West Warwick, RI 02893 USA. Tel: (800) 424-9850 or (401) 823-5200 or Fax: (401) 823-8723. E-mail: <a href="mailto:info@advanced.com">info@advanced.com</a>. Product information available online at www.advanced.com/peel.</p>
<p>Peel-A-Way is a registered trademark of Advanced Interconnections Corp.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[libevent+protobuf轻松搭建tcpserver]]></title>
<link>http://superangevil.wordpress.com/2009/10/12/tcpserver/</link>
<pubDate>Mon, 12 Oct 2009 04:36:08 +0000</pubDate>
<dc:creator>superangevil</dc:creator>
<guid>http://superangevil.wordpress.com/2009/10/12/tcpserver/</guid>
<description><![CDATA[0. 基础代码 &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // 设置某fd为O_NONBLOCK模式&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int set_n]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p>0. 基础代码</p>
<p>&#160;&#160;&#160;&#160;&#160; // 设置某fd为O_NONBLOCK模式<br />&#160;&#160;&#160;&#160;&#160; int set_non_block(int fd);</p>
<p>&#160;&#160;&#160;&#160;&#160; // server端socket流程:socket(),setsockopt(),bind(),listen(),set_non_block()，返回server_fd<br />&#160;&#160;&#160;&#160;&#160; int setup_tcp_server(int port);</p>
<p>&#160;&#160;&#160;&#160;&#160; // client端socket流程:socket(),connect()，返回连接的sockfd<br />&#160;&#160;&#160;&#160;&#160; int create_io_channel(const char *ipaddr, int port);</p>
<p>1. 搭建TCP Server<br />&#160;&#160;&#160;&#160;&#160; 下面以伪代码方式给出，错误处理省略</p>
<p>&#160;&#160;&#160;&#160;&#160; int main(int argc, char *argv[])<br />&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 初始化<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; &#8230;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // event初始化<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; event_init();<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <b>init_server</b>(port, params&#8230;);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; event_dispatch();</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return 0;<br />&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160; int init_server(short port, params&#8230;)<br />&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int listen_fd = setup_tcp_server(port);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; set_non_block(listen_fd);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 将输入的参数params&#8230; 组织为一个结构，以指针的方式存于accept_param<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; struct event* ev_accept = (struct event*)malloc(sizeof(struct event));<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; event_set(ev_accept, listen_fd, EV_READ&#124;EV_PERSIST, <b>on_accept</b>, (void*)accept_param);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; event_add(ev_accept, NULL);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; return 0;<br />&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160; void on_accept(int fd, short ev, void *arg)<br />&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int client_fd = accept(fd, (struct sockaddr*)&#38;client_addr, &#38;client_len);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; set_non_block(client_fd);</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // Disable the Nagle (TCP No Delay) algorithm<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int flag = 1;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int ret = setsockopt(client_fd, IPPROTO_TCP, TCP_NODELAY, (char*)&#38;flag, sizeof(flag));</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 设置buffer event<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 假设client_t有一个类型为struct bufferevent*的域buf_ev<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //&#160;&#160;&#160;&#160; total_len: 指示请求总长度<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //&#160;&#160;&#160;&#160; cur_size:&#160; 指示当前已经接收的请求长度<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; //&#160;&#160;&#160;&#160; data:&#160;&#160;&#160;&#160;&#160; 请求数据本身<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client_t *client = (client_t*)malloc(sizeof(client_t));<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;buf_ev = bufferevent_new(client_fd, <b>buffer_on_read</b>, <b>buffer_on_write</b>, <b>buffer_on_error</b>, client);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;total_len = 0;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;cur_size = 0;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;data = NULL;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; bufferevent_enable(client-&#62;buf_ev, EV_READ&#124;EV_WRITE);<br />&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160; void buffer_on_read(struct bufferevent *ev_buf, void *opqaue)<br />&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 读请求并处理</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client_t *client = (client_t*)opaque;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; size_t rdsz;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int sz;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (client-&#62;total_len &#60;= client-&#62;cur_size) {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 读新请求</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 获得新请求的总长度<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; rdsz = bufferevent_read(ev_buf, &#38;sz, sizeof(int));<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;total_len = sz;</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 开始读新请求数据(一次不一定能读完!)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; char *data = (char*)malloc(sz);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; rdsz = bufferevent_read(ev_buf, data, sz);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;cur_size = (int)rdsz;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;data = data;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; } else {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 继续读该请求<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; rdsz = bufferevent_read(ev_buf, client-&#62;data+client-&#62;cur_size, client-&#62;total_len-client-&#62;cur_size);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;cur_size += (int)rdsz;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (client-&#62;cur_size &#62;= client-&#62;total_len) {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 处理该(完整的)请求<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; request_t&#160; req;&#160;&#160; // 请求的数据结构(通过protobuf定义)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; response_t res;&#160;&#160; // 回应的数据结构(通过protobuf定义)</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 调用处理函数对request进行处理,并把结果写到response中<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; req.ParseFromArray((const void*)client-&#62;data, client-&#62;total_len);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; process_func(req, res);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 写回应<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; string output;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; res.SerializeToString(&#38;output);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; int status = bufferevent_write(ev_buf, output.c_str(), output.length());<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<br />&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160; void buffer_on_write(struct bufferevent *ev_buf, void *opqaue)<br />&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 作清理工作</p>
<p>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client_t *client = (client_t*)opaque;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (client-&#62;data &#38;&#38; strlen(client-&#62;data) != 0)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; free(client-&#62;data);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;data = NULL;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;total_len = 0;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; client-&#62;cur_size = 0;<br />&#160;&#160;&#160;&#160;&#160; }</p>
<p>&#160;&#160;&#160;&#160;&#160; void buffer_on_error(struct bufferevent *ev_buf, short what, void *opqaue)<br />&#160;&#160;&#160;&#160;&#160; {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; // 给出错误信息<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; division_client *client = (division_client*)opaque;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; struct sockaddr_in client_addr;<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; socklen_t len = sizeof(client_addr);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (getpeername(client-&#62;sock_fd, (struct sockaddr*)&#38;client_addr, &#38;len) == 0)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LOG_INFO(&#8220;Client(%s:%u) connection closed or Error occured &#8212; %d\n&#8221;, <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; inet_ntoa(client_addr.sin_addr), <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; ntohs(client_addr.sin_port),<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; what);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; else<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; LOG_INFO(&#8220;Client(unknown) connection closed or Error occured &#8212; %d\n&#8221;, what);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (client) {<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; if (client-&#62;data)<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; free(client-&#62;data);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; free(client);<br />&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; }<br />&#160;&#160;&#160;&#160;&#160; }</p>
<p>2. protobuf作为client与server之间的数据传输协议</p>
<p>详见 <a target="_blank" href="http://code.google.com/apis/protocolbuffers/">http://code.google.com/apis/protocolbuffers/</a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Emule ID basso]]></title>
<link>http://faberex.wordpress.com/2009/10/06/emule-id-basso/</link>
<pubDate>Tue, 06 Oct 2009 17:19:01 +0000</pubDate>
<dc:creator>faberex</dc:creator>
<guid>http://faberex.wordpress.com/2009/10/06/emule-id-basso/</guid>
<description><![CDATA[Giusto per chiarire le idee su una funzione vitale, vediamo di fare un piccolo riassunto sui possibi]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><img class="alignright size-full wp-image-2093" title="impost_rete_dream(1)" src="http://faberex.wordpress.com/files/2009/10/impost_rete_dream11.png" alt="impost_rete_dream(1)" width="303" height="285" /></p>
<p>Giusto per chiarire le idee su una funzione vitale, vediamo di fare un piccolo riassunto sui possibili “Perché” di un ID Basso.</p>
<p> </p>
<ol>
<li>Controllare se avete configurato il firewall di  XP o Vista. E’ preferibile disabilitare del tutto il firewall integrato di Windows XP e utilizzare uno esterno . Si consiglia <strong>Outpost</strong> ( con Options,Plugin,Setup,Stop su tutti) <strong>Segate</strong> e <strong>Zone Alarm</strong> per la facilità di configurazione e l’assenza di malfunzionamenti ; installatelo e poi procedete alla loro configurazione</li>
<li>Controllate se avete un router e configuratelo</li>
<li>Se continuate ad avere ID Basso domandatevi se vi serve davvero un router .Se avete un solo PC non vi serve .Procuratevi , piuttosto , un <strong>Modem USB</strong> per pochi euro.</li>
<li><strong>GRPS,ADSL</strong> <strong>Satellitare</strong> e <strong>UMTS</strong> avranno comunque un <strong>ID Basso</strong></li>
<li>In caso disperato provate a chiedere sul canale ufficiale di aiuto raggiungibile dal <strong>pulsante IRC</strong> di eMule ,ma ricordatevi che configurare un <strong>router</strong> è operazione lunga e noiosa e che dovrete cavarvela da soli più che potrete ,perché ci sono multi utenti e pochi operatori in grado di aiutarvi. Il server , quando vi collegate , assegna <strong>l’ID ALTO</strong> (maggiore di 16777216) con un semplice calcolo a partire dal vostro IP (Indicato con A.B.C.D.): IP = A.B.C.D.&#62;ID = A+256* B+256*256*C+256*256*256*D. Il server assegna ID Basso con un numero progressivo che parte da 1 per il primo eMule con ID Basso che si collega a lui e che aumenta via via per ogni altro utente con ID Basso successivo <strong>(NON DIPENDE PERCIO’ DALL’ IP)</strong></li>
<li>Se nonostante i vostri tentativi nulla accade, ecco una dritta per cercare un’ulteriore aiuto <a href="http://zirconet.wordpress.com/">http://zirconet.wordpress.com/</a>   ottimo blog di notizie e con perle tecniche per trarsi dagl’impicci .Il blog non e’ tra i più conosciuti data la sua recente comparsa ma l’autore è persona attenta e disponibile e quel che più conta risponde sempre ai quesiti inviatogli.</li>
</ol>
<p><!--more--></p>
<p><strong>Qui qualche piccola ulteriore delucidazioni su alcuni termini usati.</strong></p>
<p><strong> </strong></p>
<p><strong><span style="text-decoration:underline;">IP</span></strong><strong>: </strong>E’ l’indirizzo del vostro pc su internet, indispensabile per poter comunicare con altri computer. Viene assegnato quando vi collegate alla rete. Collegatevi al sito www-ip.com e potrete vedere il vostro. E’ bene sapere che tutti i pacchetti di dati che arrivano al nostro pc contengono solo il nostro IP, perché la rete di distribuzione conosce dove siamo e ci manda solo pacchetti i coretti ( e questo se ben pensate la dice lunga sull’effettiva privacy di Internet , ma questo e’ un altro discorso) Tutti gli IP si scrivono a gruppi di tre cifre (da 0 a 255) separati da un punto , per esempio 235.158.2.96. Non potete scegliere l’ IP che vi viene assegnato ,perche’ sono stati acquistati dalle compagnie telefoniche  e attribuiti a loro piacimento quando vi collegate. Sono detti IP pubblici perché i pc che li possiedono possono parlare direttamente su internet tra loro.</p>
<p><strong> </strong></p>
<p><strong><span style="text-decoration:underline;">Per Router o reti locali:</span></strong></p>
<p><strong> </strong></p>
<p>I seguenti intervalli di <strong>IP sono detti privati</strong> perchè non vengono utilizzati su internet ma solo per creare delle reti locali collegando più pc tra loro <strong>(LAN)</strong></p>
<p>Esempio ; 10.x.x.x</p>
<p>                 192.168.x.x</p>
<p>da……….. 172.16.0.0 a 172.31.255.25</p>
<p>Ogni <strong>LAN</strong> , se vuole comunicare su internet deve avere anche un <strong>Gateway</strong> ,cioe’ un <strong>router</strong> oppure un pc ( che chiamiamo server) collegato a internet con un modem e un programma apposito ( ad esempio ICS,Già incluso in Windows) <strong>Solo il gateway ha 2IP</strong> : uno pubblico assegnato al momento della connessione  e uno privato come tutti gli altri pc della LAN (esempio gateway con 235.158.2.96 e 10.0.0.1, gli altri Pc 10.0.0.2,10.0.0.3 ecc ,ecc.) Gli altri pc nel mondo non sanno che avete molti computer collegati perché vedranno solo l’IP pubblico del gateway.Quindi quando uno dei pc della LAN deve spedire dei dati , il gateway cambia nei pacchetti l’IP del pc che ha effettuato la trasmissione con quello pubblico e li spedisce, memorizzando inoltre quale porta ha utilizzato il pc . In ricezione tutti i dati che arrivano vengono smistati ai vari Pc della rete locale dal gateway ,perché ricorda quale porta sta utilizzando ogni pc interno . Questo meccanismo di sostituzione di IP e smistamento viene detto funzione di <strong>NAT.</strong> Ovviamente , i pc della rete locale sanno che devono passare attraverso il router o il server (cioè il gateway) perciò utilizzano automaticamente porte diverse tra di loro per parlare con il router , in modo da non aver conflitti. Il problema <strong>di ID Basso</strong> , in questi casi può essere risolto configurando <strong>il router o l’ICS di windows</strong>. In una rete locale , normalmente gli <strong>ADSL router</strong> svolgono tutte le tre funzioni <strong>: ethernet hub + router con NAT + MODEM ADSL</strong> . quindi voi vedete solo un apparecchio . Il router serve per la conversione <strong>IP PUBBLICO/IP PRIVATO</strong> , il modem manda segnali elettrici e dialoga sul cavo di rame con il modem della centrale telefonica che e’ dall’altro estremo della linea <strong>ADSL</strong>.</p>
<p><strong><span style="text-decoration:underline;">Porta</span></strong></p>
<p> </p>
<p>E’ il numero che va <strong>da 0 a 65535</strong> e serve ai pc per capire a che programma devono essere deviati tutti i dati che arrivano fra quelli che funzionano sul pc .possiamo pensare che se il pc fosse un condominio <strong>, l’IP SAREBBE L’INDIRIZZO DELL’EDIFICIO</strong> .La porta la possiamo immaginare come uno degli appartamenti interni all’edificio in cui ogni appartamento è un programma che vuole comunicare con internet. Ogni pacchetto dati che vi arriva possiede non solo l’indirizzo IP del vostro pc , ma anche la porta di destinazione per il programma che deve riceverlo. Alcune porte sono standard , come per esempio la <strong>80 per i server web . la 25 e la 110 per i server della posta </strong>. Quando usate <strong>Internet Explorer</strong> , il vostro pc apre una porta a caso fra quelle non ancora utilizzate  e si collega <strong>sempre alla porta 80 del server</strong> che ospita il sito che state visitando . SE si deve specificare una porta a mano , si usa <strong>scrivere IP: porta</strong> . Esempio 235.158.2.96:1456( indica la porta 1456 sul pc con indirizzo 235.158.2.96) tale combinazione di <strong>IP+ porta</strong> è detta  <strong>“SOCKET”</strong></p>
<p>Provate con il programma <strong>TCPWiew</strong> . Una versione più rozza è incorporata dentro windows basta fare :</p>
<p><strong>START, ESEGUI ,CMD ;</strong> ora nella finestra <strong>scrivete Netstat</strong>  seguito da invio e il gioco e’ fatto.</p>
<p> </p>
<p><strong><span style="text-decoration:underline;">ID</span></strong></p>
<p> </p>
<p>E’ un numero calcolato dal server di emule a cui vi collegate , di solito determinato dall’IP che avete su internet</p>
<p> </p>
<p><strong><span style="text-decoration:underline;">Firewall</span></strong></p>
<p> </p>
<p>Programma che serve a bloccare le intrusioni al vostro pc mentre siete collegati su internet , chiudendo tutte le porte non utilizzate e spesso consentono di bloccare o autorizzare i singoli programmi che chiedono di comunicare su internet( potrebbero essere  <strong>trojan o spyware</strong> che vi hanno infettato) Il firewall genera quindi una linea di difesa tra il vostro pc e la rete con l’obiettivo finale di controllare il flusso di informazioni che partano e arrivano al computer per verificare se queste seguono o meno criteri legittimi. Non appena un informazione esce da questi criteri , il firewal entra in azione e consente se bloccare o meno un particolare scambio di dati.</p>
<p> </p>
<p><strong>PS: Chiaro è , che tutto quanto scritto sopra va considerato in linea di massima, tutti più o meno abbiamo avuto a che fare con delle “strane presenze “ dentro i nostri pc ( accorgersi è già da considerarsi come una fortuna)</strong></p>
<p><strong>Il firewal più potente è, e rimane la vostra prudenza</strong>.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Mill-Max Enhances Custom Socket Receptacles]]></title>
<link>http://primson.wordpress.com/2009/10/05/mill-max-enhances-custom-socket-receptacles/</link>
<pubDate>Mon, 05 Oct 2009 21:45:07 +0000</pubDate>
<dc:creator>primson</dc:creator>
<guid>http://primson.wordpress.com/2009/10/05/mill-max-enhances-custom-socket-receptacles/</guid>
<description><![CDATA[Mill-Max has introduced threading and tapping capabilities (in metric and inch sizes) for implementa]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><strong><a href="http://www.mill-max.com/">Mill-Max</a></strong> has introduced threading and tapping capabilities (in metric and inch sizes) for implementation on custom socket receptacles. For specialised applications requiring a non-soldered, field-replaceable interconnect, such as a socket location terminated on a metal plate, threaded or tapped pin receptacles can offer a solution. Tapping the interior back-hole of a receptacle allows for the screw attachment of threaded mating pins.</p>
<p>The company can provide design solutions for both threaded pins and matching tapped receptacle (or vice versa) for field-replaceable interconnect applications. Mill-Max receptacles are precision machined using brass alloy 360 1/2 hard, which offers conductive and thermal properties. Every receptacle is press-fit assembled with a beryllium copper contact, available in 36 different sizes to accept a range of mating pins measuring 0.008in to 0.102in (0.2mm to 2.59mm) in diameter.</p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[k-d tools 2533 socket holder rack set]]></title>
<link>http://kdtools.wordpress.com/2009/10/05/k-d-tools-2533-socket-holder-rack-set/</link>
<pubDate>Mon, 05 Oct 2009 02:04:20 +0000</pubDate>
<dc:creator>banrong34</dc:creator>
<guid>http://kdtools.wordpress.com/2009/10/05/k-d-tools-2533-socket-holder-rack-set/</guid>
<description><![CDATA[Buy Cheap K-D Tools 2533 Socket Holder Rack Set Buy Low Price From Here Now Neatly stores 1 4&#8243;]]></description>
<content:encoded><![CDATA[<div class='snap_preview'><p><b>Buy Cheap  K-D Tools 2533 Socket Holder Rack Set  </b><br /><a href="http://www.amazon.com/dp/B000CD1AIQ?tag=cheap.kd-tools.sales-20"><img src='http://ecx.images-amazon.com/images/I/31GUHsVzpyL.jpg' width='300'></a><br /><a href="http://www.amazon.com/dp/B000CD1AIQ?tag=cheap.kd-tools.sales-20"><font size="5"><b>Buy  Low Price From Here Now </b></font></a><br />Neatly stores 1 4&#8243;, 3 8&#8243;, and 1 2&#8243; square drive sockets. Mount on wall or in tool box. Each holder holds 16 sockets on movable clips. All steel construction&#8230;&#8230;..<br style="clear:both;"><a href="http://www.amazon.com/dp/B000CD1AIQ?tag=cheap.kd-tools.sales-20"><b> Readmore </b></a><br />
<h2>Technical Details</h2>
<p> &#8211; Sold Individually <br /> <a href="http://www.amazon.com/dp/B000CD1AIQ?tag=cheap.kd-tools.sales-20"><b>See more technical details </b></a><!--more--><br /><img src="http://banrong.laikeng.com/images/ico_customer_reviews.gif" alt="Customer Buzz" align="absbottom" border="0" />
<div style="background-color:#CCCCCC;height:13px;width:60px;float:left;">
<div style="background-image:url('http://banrong.laikeng.com/images/starbg.gif');width:60px;height:13px;float:left;">
<div style="height:13px;width:60px;float:left;background-image:url('http://banrong.laikeng.com/images/star.png');"> </div>
</div>
</div>
<p>&#160;<span class="rating">&#8220;good socket organizer&#8221;</span>&#160;<span class="reviewdate">2009-08-29</span><br />By <b>B. Yeung</b> (San Francisco,CA USA)<br />Good price for 1/4, 3/8 and 1/2 drive socket organizer. wish they sell it in all 3/8 drive in 3 per pack.</p>
<p><b>Images Product</b><br /><a target='_blank' href='http://ecx.images-amazon.com/images/I/31GUHsVzpyL.jpg'><img src='http://ecx.images-amazon.com/images/I/31GUHsVzpyL.jpg' width='240px' border='0' /></a><br /><a href="http://www.amazon.com/dp/B000CD1AIQ?tag=cheap.kd-tools.sales-20"><font size="2"><b>Buy K-D Tools 2533 Socket Holder Rack Set Now </b></font></a></p>
</div>]]></content:encoded>
</item>
<item>
<title><![CDATA[Guía para comprar una Placa Base (Motherboard o Mainboard)]]></title>
<link>http://silverfenix7.wordpress.com/2009/10/02/guia-para-comprar-una-placa-base-motherboard-o-mainboard/</link>
<pubDate>Thu, 01 Oct 2009 22:17:39 +0000</pubDate>
<dc:creator>silverfenix7</dc:creator>
<guid>http://silverfenix7.wordpress.com/2009/10/02/guia-para-comprar-una-placa-base-motherboard-o-mainboard/</guid>
<description><![CDATA[La placa base (Motherboard o Mainboard) es el soporte básico de un ordenador de ella depende varios ]]></description>
<content:encoded><![CDATA[La placa base (Motherboard o Mainboard) es el soporte básico de un ordenador de ella depende varios ]]></content:encoded>
</item>

</channel>
</rss>
