Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
briar
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
578
Issues
578
List
Boards
Labels
Milestones
Merge Requests
8
Merge Requests
8
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
briar
briar
Commits
91cb3ce7
Commit
91cb3ce7
authored
Nov 23, 2012
by
akwizgran
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Modem implementation using jSSC (untested).
parent
7f1b01be
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
339 additions
and
0 deletions
+339
-0
jssc-0.9-briar.jar
libs/jssc-0.9-briar.jar
+0
-0
Modem.java
src/net/sf/briar/plugins/modem/Modem.java
+35
-0
ModemImpl.java
src/net/sf/briar/plugins/modem/ModemImpl.java
+304
-0
No files found.
libs/jssc-0.9-briar.jar
0 → 100644
View file @
91cb3ce7
File added
src/net/sf/briar/plugins/modem/Modem.java
0 → 100644
View file @
91cb3ce7
package
net
.
sf
.
briar
.
plugins
.
modem
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
interface
Modem
{
/**
* Call this method once after creating the modem. If an exception is
* thrown, the modem cannot be used.
*/
void
init
()
throws
IOException
;
/**
* Initiates an outgoing call and returns true if the call connects. If the
* call does not connect the modem is hung up.
*/
boolean
dial
(
String
number
)
throws
IOException
;
/** Returns a stream for reading from the currently connected call. */
InputStream
getInputStream
();
/** Returns a stream for writing to the currently connected call. */
OutputStream
getOutputStream
();
/** Hangs up the modem, ending the currently connected call. */
void
hangUp
()
throws
IOException
;
interface
Callback
{
/** Called when an incoming call connects. */
void
incomingCallConnected
();
}
}
src/net/sf/briar/plugins/modem/ModemImpl.java
0 → 100644
View file @
91cb3ce7
package
net
.
sf
.
briar
.
plugins
.
modem
;
import
static
java
.
util
.
logging
.
Level
.
INFO
;
import
static
java
.
util
.
logging
.
Level
.
WARNING
;
import
static
jssc
.
SerialPort
.
PURGE_RXCLEAR
;
import
static
jssc
.
SerialPort
.
PURGE_TXCLEAR
;
import
java.io.IOException
;
import
java.io.InputStream
;
import
java.io.OutputStream
;
import
java.util.concurrent.BlockingQueue
;
import
java.util.concurrent.LinkedBlockingQueue
;
import
java.util.concurrent.atomic.AtomicBoolean
;
import
java.util.logging.Logger
;
import
jssc.SerialPort
;
import
jssc.SerialPortEvent
;
import
jssc.SerialPortEventListener
;
import
jssc.SerialPortException
;
class
ModemImpl
implements
Modem
,
SerialPortEventListener
{
private
static
final
Logger
LOG
=
Logger
.
getLogger
(
ModemImpl
.
class
.
getName
());
private
static
final
int
MAX_LINE_LENGTH
=
256
;
private
static
final
int
[]
BAUD_RATES
=
{
256000
,
128000
,
115200
,
57600
,
38400
,
19200
,
14400
,
9600
,
4800
,
1200
};
private
static
final
int
OK_TIMEOUT
=
5
*
1000
;
// Milliseconds
private
static
final
int
CONNECT_TIMEOUT
=
60
*
1000
;
// Milliseconds
private
final
Callback
callback
;
private
final
SerialPort
port
;
private
final
AtomicBoolean
initialised
,
offHook
,
connected
;
private
final
byte
[]
line
;
private
int
lineLen
=
0
;
// A fresh queue is used for each connection
private
volatile
BlockingQueue
<
byte
[]>
received
;
ModemImpl
(
Callback
callback
,
String
portName
)
{
this
.
callback
=
callback
;
port
=
new
SerialPort
(
portName
);
initialised
=
new
AtomicBoolean
(
false
);
offHook
=
new
AtomicBoolean
(
false
);
connected
=
new
AtomicBoolean
(
false
);
line
=
new
byte
[
MAX_LINE_LENGTH
];
received
=
new
LinkedBlockingQueue
<
byte
[]>();
}
public
void
init
()
throws
IOException
{
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Initialising"
);
try
{
// Open the serial port
if
(!
port
.
openPort
())
throw
new
IOException
(
"Failed to open serial port"
);
// Find a suitable baud rate
boolean
foundBaudRate
=
false
;
for
(
int
baudRate
:
BAUD_RATES
)
{
if
(
port
.
setParams
(
baudRate
,
8
,
1
,
0
))
{
foundBaudRate
=
true
;
break
;
}
}
if
(!
foundBaudRate
)
throw
new
IOException
(
"Could not find a suitable baud rate"
);
// Listen for incoming data and hangup events
port
.
addEventListener
(
this
);
// Initialise the modem
port
.
purgePort
(
PURGE_RXCLEAR
|
PURGE_TXCLEAR
);
port
.
writeBytes
(
"ATZ\r\n"
.
getBytes
(
"US-ASCII"
));
// Reset
port
.
writeBytes
(
"ATE0\r\n"
.
getBytes
(
"US-ASCII"
));
// Echo off
}
catch
(
SerialPortException
e
)
{
throw
new
IOException
(
e
.
toString
());
}
try
{
// Wait for the modem to respond "OK"
synchronized
(
initialised
)
{
if
(!
initialised
.
get
())
initialised
.
wait
(
OK_TIMEOUT
);
if
(!
initialised
.
get
())
throw
new
IOException
(
"Modem did not respond"
);
}
}
catch
(
InterruptedException
e
)
{
if
(
LOG
.
isLoggable
(
WARNING
))
LOG
.
warning
(
"Interrupted while initialising modem"
);
Thread
.
currentThread
().
interrupt
();
throw
new
IOException
(
"Interrupted while initialising modem"
);
}
}
public
boolean
dial
(
String
number
)
throws
IOException
{
if
(
offHook
.
getAndSet
(
true
))
{
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Not dialling - call in progress"
);
return
false
;
}
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Dialling"
);
try
{
port
.
writeBytes
((
"ATDT"
+
number
+
"\r\n"
).
getBytes
(
"US-ASCII"
));
}
catch
(
SerialPortException
e
)
{
throw
new
IOException
(
e
.
toString
());
}
try
{
synchronized
(
connected
)
{
if
(!
connected
.
get
())
connected
.
wait
(
CONNECT_TIMEOUT
);
}
}
catch
(
InterruptedException
e
)
{
if
(
LOG
.
isLoggable
(
WARNING
))
LOG
.
warning
(
"Interrupted while connecting outgoing call"
);
Thread
.
currentThread
().
interrupt
();
throw
new
IOException
(
"Interrupted while connecting outgoing call"
);
}
if
(
connected
.
get
())
return
true
;
hangUp
();
return
false
;
}
public
InputStream
getInputStream
()
{
return
new
ModemInputStream
(
received
);
}
public
OutputStream
getOutputStream
()
{
return
new
ModemOutputStream
();
}
public
void
hangUp
()
throws
IOException
{
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Hanging up"
);
try
{
port
.
setDTR
(
false
);
}
catch
(
SerialPortException
e
)
{
throw
new
IOException
(
e
.
toString
());
}
received
.
add
(
new
byte
[
0
]);
// Empty buffer indicates EOF
received
=
new
LinkedBlockingQueue
<
byte
[]>();
connected
.
set
(
false
);
offHook
.
set
(
false
);
}
public
void
serialEvent
(
SerialPortEvent
ev
)
{
try
{
if
(
ev
.
isRXCHAR
())
{
byte
[]
b
=
port
.
readBytes
();
if
(
connected
.
get
())
received
.
add
(
b
);
else
handleText
(
b
);
}
else
if
(
ev
.
isDSR
()
&&
ev
.
getEventValue
()
==
0
)
{
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Remote end hung up"
);
hangUp
();
}
}
catch
(
IOException
e
)
{
if
(
LOG
.
isLoggable
(
WARNING
))
LOG
.
warning
(
e
.
toString
());
}
catch
(
SerialPortException
e
)
{
if
(
LOG
.
isLoggable
(
WARNING
))
LOG
.
warning
(
e
.
toString
());
}
}
private
void
handleText
(
byte
[]
b
)
throws
IOException
{
if
(
lineLen
+
b
.
length
>
MAX_LINE_LENGTH
)
throw
new
IOException
(
"Line too long"
);
for
(
int
i
=
0
;
i
<
b
.
length
;
i
++)
{
line
[
lineLen
]
=
b
[
i
];
if
(
b
[
i
]
==
'\n'
)
{
String
s
=
new
String
(
line
,
0
,
lineLen
,
"US-ASCII"
).
trim
();
lineLen
=
0
;
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Modem status: "
+
s
);
if
(
s
.
startsWith
(
"CONNECT"
))
{
// There might be data in the buffer as well as text
int
off
=
i
+
1
;
if
(
off
<
b
.
length
)
{
byte
[]
data
=
new
byte
[
b
.
length
-
off
];
System
.
arraycopy
(
b
,
off
,
data
,
0
,
data
.
length
);
received
.
add
(
data
);
}
synchronized
(
connected
)
{
if
(!
connected
.
getAndSet
(
true
))
connected
.
notifyAll
();
}
return
;
}
else
if
(
s
.
equals
(
"OK"
))
{
synchronized
(
initialised
)
{
if
(!
initialised
.
getAndSet
(
true
))
initialised
.
notifyAll
();
}
}
else
if
(
s
.
equals
(
"RING"
))
{
// FIXME: Don't do this on the event thread
answer
();
}
}
else
{
lineLen
++;
}
}
}
private
void
answer
()
throws
IOException
{
if
(
offHook
.
getAndSet
(
true
))
{
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Not answering - call in progress"
);
return
;
}
if
(
LOG
.
isLoggable
(
INFO
))
LOG
.
info
(
"Answering"
);
try
{
port
.
writeBytes
(
"ATA\r\n"
.
getBytes
(
"US-ASCII"
));
}
catch
(
SerialPortException
e
)
{
throw
new
IOException
(
e
.
toString
());
}
try
{
synchronized
(
connected
)
{
if
(!
connected
.
get
())
connected
.
wait
(
CONNECT_TIMEOUT
);
}
}
catch
(
InterruptedException
e
)
{
if
(
LOG
.
isLoggable
(
WARNING
))
LOG
.
warning
(
"Interrupted while connecting incoming call"
);
Thread
.
currentThread
().
interrupt
();
throw
new
IOException
(
"Interrupted while connecting incoming call"
);
}
if
(
connected
.
get
())
callback
.
incomingCallConnected
();
else
hangUp
();
}
private
static
class
ModemInputStream
extends
InputStream
{
private
final
BlockingQueue
<
byte
[]>
received
;
private
byte
[]
buf
=
null
;
private
int
offset
=
0
;
private
ModemInputStream
(
BlockingQueue
<
byte
[]>
received
)
{
this
.
received
=
received
;
}
@Override
public
int
read
()
throws
IOException
{
getBufferIfNecessary
();
if
(
buf
.
length
==
0
)
return
-
1
;
return
buf
[
offset
++];
}
@Override
public
int
read
(
byte
[]
b
)
throws
IOException
{
getBufferIfNecessary
();
if
(
buf
.
length
==
0
)
return
-
1
;
int
len
=
Math
.
min
(
b
.
length
,
buf
.
length
-
offset
);
System
.
arraycopy
(
buf
,
offset
,
b
,
0
,
len
);
offset
+=
len
;
return
len
;
}
@Override
public
int
read
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
getBufferIfNecessary
();
if
(
buf
.
length
==
0
)
return
-
1
;
len
=
Math
.
min
(
len
,
buf
.
length
-
offset
);
System
.
arraycopy
(
buf
,
offset
,
b
,
off
,
len
);
offset
+=
len
;
return
len
;
}
private
void
getBufferIfNecessary
()
throws
IOException
{
if
(
buf
==
null
||
offset
==
buf
.
length
)
{
try
{
buf
=
received
.
take
();
}
catch
(
InterruptedException
e
)
{
if
(
LOG
.
isLoggable
(
WARNING
))
LOG
.
warning
(
"Interrupted while reading"
);
Thread
.
currentThread
().
interrupt
();
throw
new
IOException
(
e
.
toString
());
}
offset
=
0
;
}
}
}
private
class
ModemOutputStream
extends
OutputStream
{
@Override
public
void
write
(
int
b
)
throws
IOException
{
try
{
port
.
writeByte
((
byte
)
b
);
}
catch
(
SerialPortException
e
)
{
throw
new
IOException
(
e
.
toString
());
}
}
@Override
public
void
write
(
byte
[]
b
)
throws
IOException
{
try
{
port
.
writeBytes
(
b
);
}
catch
(
SerialPortException
e
)
{
throw
new
IOException
(
e
.
toString
());
}
}
@Override
public
void
write
(
byte
[]
b
,
int
off
,
int
len
)
throws
IOException
{
if
(
len
<
b
.
length
)
{
byte
[]
copy
=
new
byte
[
len
];
System
.
arraycopy
(
b
,
off
,
copy
,
0
,
len
);
write
(
copy
);
}
else
{
write
(
b
);
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment