Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Emmanuel Lécharny
Le 10/02/16 22:11, Jon V. a écrit :
> I would have thought the reason SSL Filter needs to be before Proxy is
> because the SSL handshaking from the client side would get proxied away
> from the SSL Filter.

That too. But all in all, the handshake is just an exchange of data, as
any other data beinge exchanged later on. It can also be split in
pieces, the wame way...



Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Jon V.
I would have thought the reason SSL Filter needs to be before Proxy is
because the SSL handshaking from the client side would get proxied away
from the SSL Filter.

On Wed, Feb 10, 2016 at 12:57 PM, Emmanuel Lécharny 
wrote:

> Le 10/02/16 18:16, Norbert Irmer a écrit :
> >> Ok, but you can insert teh SslFilter *before* the proxyFilter. Once you
> >> get the ProxyConnector instance, get the connector and do :
> >
> > Well, I am using a patched QuickFixJ version, in which the control flow
> is a bit different.
> >
> > Here is an excerpt from the code they are using:
> >
> >
> >   CompositeIoFilterChainBuilder ioFilterChainBuilder = new
> CompositeIoFilterChainBuilder(
> > userIoFilterChainBuilder);
> >
> > boolean useProxy = proxyType != null && proxyPort > 0 &&
> > socketAddresses[0] instanceof
> InetSocketAddress;
> >
> >
> > SslFilter sslFilter = null;
> > if (sslEnabled) {
> > boolean autoStart = !useProxy;
> > sslFilter = installSslFilter(ioFilterChainBuilder,
> autoStart);
> > }
> >
> >
>  ioFilterChainBuilder.addLast(FIXProtocolCodecFactory.FILTER_NAME,
> > new ProtocolCodecFilter(new
> FIXProtocolCodecFactory()));
> >
> > if (useProxy) {
> > SocketConnector socketConnector = new
> NioSocketConnector();
> >
>  socketConnector.setFilterChainBuilder(ioFilterChainBuilder);
> > ioConnector = ProtocolFactory.createIoProxyConnector(
> socketConnector,
> > (InetSocketAddress) socketAddresses[0], new
> InetSocketAddress(proxyHost,
> > proxyPort), proxyType, proxyVersion,
> proxyUser, proxyPassword,
> > proxyDomain, proxyWorkstation);
> > } else {
> > ioConnector =
> ProtocolFactory.createIoConnector(socketAddresses[0]);
> > ioConnector.setFilterChainBuilder(ioFilterChainBuilder);
> > }
> >
> > ioHandler = new InitiatorIoHandler(fixSession, sslFilter,
> networkingOptions, eventHandlingStrategy);
> > }
> >
> > private SslFilter installSslFilter(CompositeIoFilterChainBuilder
> ioFilterChainBuilder,
> >boolean autoStart)
> > throws GeneralSecurityException {
> > SslFilter sslFilter = new
> SslFilter(SSLContextFactory.getInstance(keyStoreName,
> > keyStorePassword.toCharArray()), autoStart);
> > if (enableProtocole != null)
> > sslFilter.setEnabledProtocols(enableProtocole);
> > if (cipherSuites != null)
> > sslFilter.setEnabledCipherSuites(cipherSuites);
> > sslFilter.setUseClientMode(true);
> > ioFilterChainBuilder.addLast(SSLSupport.FILTER_NAME,
> sslFilter);
> > return sslFilter;
> > }
> >
> >
> > Sure, with a lot of time, I could possibly rewrite the code, to swap the
> positions of the filters in the filterchain.
> >
> > But  I see little sense in it, since the code is working. The only
> problem I have, is that I get this deadlock after a few minutes or so.
> How can you say the code is working when you get a deadlock ?
>
> As Jon said, having the ProcyFilter *before* the SSLFilter in the chain
> is not the right thing. The reason being that you may perfectly get
> fragmented TCP buffers, and the proxy might not be able to deal with
> de-fragmentation when it comes to encrypted data.
>
> I suggest that you patch teh code to first call the installSslFilter
> method after the proxy has been created, and in the
> installSslFiltermethod, use addFirst() instead of addLast().
>
> Otherwise, you can also check with the latest trunk revision I built
> today to see if it's any better (on http://people.apache.org/~elecharny)
>
>


Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Emmanuel Lécharny
Le 10/02/16 18:16, Norbert Irmer a écrit :
>> Ok, but you can insert teh SslFilter *before* the proxyFilter. Once you
>> get the ProxyConnector instance, get the connector and do :
>  
> Well, I am using a patched QuickFixJ version, in which the control flow is a 
> bit different.
>
> Here is an excerpt from the code they are using:
>
>
>   CompositeIoFilterChainBuilder ioFilterChainBuilder = new 
> CompositeIoFilterChainBuilder(
> userIoFilterChainBuilder);
>
> boolean useProxy = proxyType != null && proxyPort > 0 &&
> socketAddresses[0] instanceof 
> InetSocketAddress;
>
>
> SslFilter sslFilter = null;
> if (sslEnabled) {
> boolean autoStart = !useProxy;
> sslFilter = installSslFilter(ioFilterChainBuilder, autoStart);
> }
>
> ioFilterChainBuilder.addLast(FIXProtocolCodecFactory.FILTER_NAME,
> new ProtocolCodecFilter(new FIXProtocolCodecFactory()));
>
> if (useProxy) {
> SocketConnector socketConnector = new NioSocketConnector();
> socketConnector.setFilterChainBuilder(ioFilterChainBuilder);
> ioConnector = ProtocolFactory.createIoProxyConnector( 
> socketConnector,
> (InetSocketAddress) socketAddresses[0], new 
> InetSocketAddress(proxyHost,
> proxyPort), proxyType, proxyVersion, 
> proxyUser, proxyPassword,
> proxyDomain, proxyWorkstation);
> } else {
> ioConnector = 
> ProtocolFactory.createIoConnector(socketAddresses[0]);
> ioConnector.setFilterChainBuilder(ioFilterChainBuilder);
> }
>
> ioHandler = new InitiatorIoHandler(fixSession, sslFilter, 
> networkingOptions, eventHandlingStrategy);
> }
>
> private SslFilter installSslFilter(CompositeIoFilterChainBuilder 
> ioFilterChainBuilder,
>boolean autoStart)
> throws GeneralSecurityException {
> SslFilter sslFilter = new 
> SslFilter(SSLContextFactory.getInstance(keyStoreName,
> keyStorePassword.toCharArray()), autoStart);
> if (enableProtocole != null)
> sslFilter.setEnabledProtocols(enableProtocole);
> if (cipherSuites != null)
> sslFilter.setEnabledCipherSuites(cipherSuites);
> sslFilter.setUseClientMode(true);
> ioFilterChainBuilder.addLast(SSLSupport.FILTER_NAME, sslFilter);
> return sslFilter;
> }
>
>
> Sure, with a lot of time, I could possibly rewrite the code, to swap the 
> positions of the filters in the filterchain.
>
> But  I see little sense in it, since the code is working. The only problem I 
> have, is that I get this deadlock after a few minutes or so.
How can you say the code is working when you get a deadlock ?

As Jon said, having the ProcyFilter *before* the SSLFilter in the chain
is not the right thing. The reason being that you may perfectly get
fragmented TCP buffers, and the proxy might not be able to deal with
de-fragmentation when it comes to encrypted data.

I suggest that you patch teh code to first call the installSslFilter
method after the proxy has been created, and in the
installSslFiltermethod, use addFirst() instead of addLast().

Otherwise, you can also check with the latest trunk revision I built
today to see if it's any better (on http://people.apache.org/~elecharny)



Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Norbert Irmer

> Ok, but you can insert teh SslFilter *before* the proxyFilter. Once you
> get the ProxyConnector instance, get the connector and do :
 
Well, I am using a patched QuickFixJ version, in which the control flow is a 
bit different.

Here is an excerpt from the code they are using:


  CompositeIoFilterChainBuilder ioFilterChainBuilder = new 
CompositeIoFilterChainBuilder(
userIoFilterChainBuilder);

boolean useProxy = proxyType != null && proxyPort > 0 &&
socketAddresses[0] instanceof InetSocketAddress;


SslFilter sslFilter = null;
if (sslEnabled) {
boolean autoStart = !useProxy;
sslFilter = installSslFilter(ioFilterChainBuilder, autoStart);
}

ioFilterChainBuilder.addLast(FIXProtocolCodecFactory.FILTER_NAME,
new ProtocolCodecFilter(new FIXProtocolCodecFactory()));

if (useProxy) {
SocketConnector socketConnector = new NioSocketConnector();
socketConnector.setFilterChainBuilder(ioFilterChainBuilder);
ioConnector = ProtocolFactory.createIoProxyConnector( 
socketConnector,
(InetSocketAddress) socketAddresses[0], new 
InetSocketAddress(proxyHost,
proxyPort), proxyType, proxyVersion, proxyUser, 
proxyPassword,
proxyDomain, proxyWorkstation);
} else {
ioConnector = 
ProtocolFactory.createIoConnector(socketAddresses[0]);
ioConnector.setFilterChainBuilder(ioFilterChainBuilder);
}

ioHandler = new InitiatorIoHandler(fixSession, sslFilter, 
networkingOptions, eventHandlingStrategy);
}

private SslFilter installSslFilter(CompositeIoFilterChainBuilder 
ioFilterChainBuilder,
   boolean autoStart)
throws GeneralSecurityException {
SslFilter sslFilter = new 
SslFilter(SSLContextFactory.getInstance(keyStoreName,
keyStorePassword.toCharArray()), autoStart);
if (enableProtocole != null)
sslFilter.setEnabledProtocols(enableProtocole);
if (cipherSuites != null)
sslFilter.setEnabledCipherSuites(cipherSuites);
sslFilter.setUseClientMode(true);
ioFilterChainBuilder.addLast(SSLSupport.FILTER_NAME, sslFilter);
return sslFilter;
}


Sure, with a lot of time, I could possibly rewrite the code, to swap the 
positions of the filters in the filterchain.

But  I see little sense in it, since the code is working. The only problem I 
have, is that I get this deadlock after a few minutes or so.

At the moment, as a workaround, I simply disabled the "synchronized(handler) { 
... }" in ProxyFilter.writeData(),
I think for my special case this will work.

I don't think it is possible, that the filterchains are traverted in the same 
order for reading and writing.
  

 



Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Emmanuel Lécharny
Le 10/02/16 16:37, Norbert Irmer a écrit :
>> seems like you have installed the proxy filter before the ssl filter in
>> your chain. Can you do the opposite ?
> I don't build the chain manually, I simply use a "ProxyConnector" (from 
> package "org.apache.mina.proxy")
> to make a proxy connection (this also explains, why I had the 
> SslFilter/autoStart problem in my earlier mail).
>
> "ProxyConnector" does the following in "setConnector": 
>
>
>   private void setConnector(final SocketConnector connector) {
> if (connector == null) {
> throw new IllegalArgumentException("connector cannot be null");
> }
>
> this.connector = connector;
> String className = ProxyFilter.class.getName();
>
> // Removes an old ProxyFilter instance from the chain
> if (connector.getFilterChain().contains(className)) {
> connector.getFilterChain().remove(className);
> }
>
> // Insert the ProxyFilter as the first filter in the filter chain 
> builder
> connector.getFilterChain().addFirst(className, proxyFilter);
> }
Ok, but you can insert teh SslFilter *before* the proxyFilter. Once you
get the ProxyConnector instance, get the connector and do :


SslFilter sslFilter = new SslFilter(BogusSslContextFactory
.getInstance(true));
connector.getFilterChain().addFirst( "MySslFilter", sslFilter );


Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Norbert Irmer

> seems like you have installed the proxy filter before the ssl filter in
> your chain. Can you do the opposite ?

I don't build the chain manually, I simply use a "ProxyConnector" (from package 
"org.apache.mina.proxy")
to make a proxy connection (this also explains, why I had the 
SslFilter/autoStart problem in my earlier mail).

"ProxyConnector" does the following in "setConnector": 


  private void setConnector(final SocketConnector connector) {
if (connector == null) {
throw new IllegalArgumentException("connector cannot be null");
}

this.connector = connector;
String className = ProxyFilter.class.getName();

// Removes an old ProxyFilter instance from the chain
if (connector.getFilterChain().contains(className)) {
connector.getFilterChain().remove(className);
}

// Insert the ProxyFilter as the first filter in the filter chain 
builder
connector.getFilterChain().addFirst(className, proxyFilter);
}


Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Emmanuel Lécharny


Le 10/02/16 13:11, Norbert Irmer a écrit :
> Hello,
>
> I did a "threaddump" with visualvm in the deadlock situation (not sure if 
> this is what you wanted, but I don't see
> anything else), it shows the same deadlock situation (at the bottom of this 
> mail), as in my previous mail.

Thanks !


seems like you have installed the proxy filter before the ssl filter in
your chain. Can you do the opposite ?



Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Norbert Irmer
Hello,

I did a "threaddump" with visualvm in the deadlock situation (not sure if this 
is what you wanted, but I don't see
anything else), it shows the same deadlock situation (at the bottom of this 
mail), as in my previous mail.


2016-02-10 13:04:58
Full thread dump Java HotSpot(TM) 64-Bit Server VM (25.60-b23 mixed mode):

"Thread-7" #29 daemon prio=5 os_prio=0 tid=0x1ed49000 nid=0xfb0 
runnable [0x1f66e000]
   java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:284)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:326)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:178)
- locked <0x00076ee06830> (a java.io.InputStreamReader)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:161)
at java.io.BufferedReader.skip(BufferedReader.java:411)
- locked <0x00076ee06830> (a java.io.InputStreamReader)
at 
de.digitec.d3.pricing.streaming.impl.StreamingChannelImpl.readMessage(StreamingChannelImpl.java:331)
at de.digitec.d3.pricing.streaming.impl.Session.run(Session.java:116)
- locked <0x00076ee068c8> (a java.lang.Object)

   Locked ownable synchronizers:
- None

"SiDispatcher_ReadLoop" #28 prio=5 os_prio=0 tid=0x1ed48800 nid=0x17fc 
waiting on condition [0x221de000]
   java.lang.Thread.State: WAITING (parking)
at sun.misc.Unsafe.park(Native Method)
- parking to wait for  <0x00076f04c960> (a 
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
at 
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2039)
at 
de.digitec.d3.pricing.streaming.impl.SessionManagerAbstractImpl.readMessage(SessionManagerAbstractImpl.java:49)
at 
de.digitec.d3.pricing.streaming.impl.SiDispatcher.run(SiDispatcher.java:455)
at java.lang.Thread.run(Thread.java:745)

   Locked ownable synchronizers:
- None

"Thread-6" #27 daemon prio=5 os_prio=0 tid=0x1ed47800 nid=0x1674 
runnable [0x2202f000]
   java.lang.Thread.State: RUNNABLE
at java.net.DualStackPlainSocketImpl.accept0(Native Method)
at 
java.net.DualStackPlainSocketImpl.socketAccept(DualStackPlainSocketImpl.java:131)
at 
java.net.AbstractPlainSocketImpl.accept(AbstractPlainSocketImpl.java:409)
at java.net.PlainSocketImpl.accept(PlainSocketImpl.java:199)
- locked <0x00076ee102c8> (a java.net.SocksSocketImpl)
at java.net.ServerSocket.implAccept(ServerSocket.java:545)
at java.net.ServerSocket.accept(ServerSocket.java:513)
at 
de.digitec.d3.pricing.streaming.impl.SocketAcceptor.accept(SocketAcceptor.java:152)
at 
de.digitec.d3.pricing.streaming.impl.SocketAcceptor.run(SocketAcceptor.java:128)

   Locked ownable synchronizers:
- None

"SessionManagerStreamingImpl_Timer" #26 daemon prio=5 os_prio=0 
tid=0x1ed47000 nid=0x1bbc in Object.wait() [0x21d9f000]
   java.lang.Thread.State: TIMED_WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.util.TimerThread.mainLoop(Timer.java:552)
- locked <0x00076ee18180> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)

   Locked ownable synchronizers:
- None

"SiDispatcher_Timer" #25 prio=5 os_prio=0 tid=0x1ed46000 nid=0x12d8 in 
Object.wait() [0x2030f000]
   java.lang.Thread.State: WAITING (on object monitor)
at java.lang.Object.wait(Native Method)
at java.lang.Object.wait(Object.java:502)
at java.util.TimerThread.mainLoop(Timer.java:526)
- locked <0x00076ee18350> (a java.util.TaskQueue)
at java.util.TimerThread.run(Timer.java:505)

   Locked ownable synchronizers:
- None

"RMI TCP Connection(2)-172.16.125.86" #24 daemon prio=5 os_prio=0 
tid=0x1ed45800 nid=0x1704 runnable [0x218ad000]
   java.lang.Thread.State: RUNNABLE
at java.net.SocketInputStream.socketRead0(Native Method)
at java.net.SocketInputStream.socketRead(SocketInputStream.java:116)
at java.net.SocketInputStream.read(SocketInputStream.java:170)
at java.net.SocketInputStream.read(SocketInputStream.java:141)
at java.io.BufferedInputStream.fill(BufferedInputStream.java:246)
at java.io.BufferedInputStream.read(BufferedInputStream.java:265)
- locked <0x00076ee12618> (a java.io.BufferedInputStream)
at java.io.FilterInput

Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Emmanuel Lécharny
Le 10/02/16 10:08, Norbert Irmer a écrit :
> I attached a stacktrace of the two threads, which are in a deadlock.
>
> Jon maybe right, when saying the write stack is threadsafe, the problem is, 
> that simultaneously
> a read operation is going on, and both stacks use the same filters.

The stakcs you provided are useless. What we really need here is the
full stack dump.

Also note that the filter is instanciated as many times as there are
sessions, so the real problem is when a session is processed by two
different threads. That might make sense in some use case, but we have
to guarantee that the encryption and decryption of messages are done
fully before dealing with the next message. This is the reason we have a
lock in the SslHandler.

That being said, there *is* something wrong and we need to figure out
what it is and how to get it fixed.



Re: Deadlock when using SslFilter and ProxyFilter together

2016-02-10 Thread Norbert Irmer
I attached a stacktrace of the two threads, which are in a deadlock.

Jon maybe right, when saying the write stack is threadsafe, the problem is, 
that simultaneously
a read operation is going on, and both stacks use the same filters.

Thread "NioProcessor-2": 
 
flushScheduledEvents():308, SslHandler {org.apache.mina.filter.ssl}
messageReceived():534, SslFilter {org.apache.mina.filter.ssl}
callNextMessageReceived():542, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
access$1300():48, DefaultIoFilterChain {org.apache.mina.core.filterchain}
messageReceived():943, DefaultIoFilterChain$EntryImpl$1 
{org.apache.mina.core.filterchain}
messageReceived():153, ProxyFilter {org.apache.mina.proxy.filter}
callNextMessageReceived():542, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
access$1300():48, DefaultIoFilterChain {org.apache.mina.core.filterchain}
messageReceived():943, DefaultIoFilterChain$EntryImpl$1 
{org.apache.mina.core.filterchain}
messageReceived():109, IoFilterAdapter {org.apache.mina.core.filterchain}
callNextMessageReceived():542, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
fireMessageReceived():535, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
read():684, AbstractPollingIoProcessor {org.apache.mina.core.polling}
process():638, AbstractPollingIoProcessor {org.apache.mina.core.polling}
process():627, AbstractPollingIoProcessor {org.apache.mina.core.polling}
access$600():68, AbstractPollingIoProcessor {org.apache.mina.core.polling}
run():1096, AbstractPollingIoProcessor$Processor {org.apache.mina.core.polling}
run():64, NamePreservingRunnable {org.apache.mina.util}
runWorker():1142, ThreadPoolExecutor {java.util.concurrent}
run():617, ThreadPoolExecutor$Worker {java.util.concurrent}
run():745, Thread {java.lang}


Thread "FixMessageProcessor(0)::ABFX":

writeData():209, ProxyFilter {org.apache.mina.proxy.filter}
filterWrite():192, ProxyFilter {org.apache.mina.proxy.filter}
callPreviousFilterWrite():625, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
access$1500():48, DefaultIoFilterChain {org.apache.mina.core.filterchain}
filterWrite():953, DefaultIoFilterChain$EntryImpl$1 
{org.apache.mina.core.filterchain}
flushScheduledEvents():316, SslHandler {org.apache.mina.filter.ssl}
filterWrite():653, SslFilter {org.apache.mina.filter.ssl}
callPreviousFilterWrite():625, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
access$1500():48, DefaultIoFilterChain {org.apache.mina.core.filterchain}
filterWrite():953, DefaultIoFilterChain$EntryImpl$1 
{org.apache.mina.core.filterchain}
filterWrite():321, ProtocolCodecFilter {org.apache.mina.filter.codec}
callPreviousFilterWrite():625, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
access$1500():48, DefaultIoFilterChain {org.apache.mina.core.filterchain}
filterWrite():953, DefaultIoFilterChain$EntryImpl$1 
{org.apache.mina.core.filterchain}
filterWrite():877, DefaultIoFilterChain$TailFilter 
{org.apache.mina.core.filterchain}
callPreviousFilterWrite():625, DefaultIoFilterChain 
{org.apache.mina.core.filterchain}
fireFilterWrite():618, DefaultIoFilterChain {org.apache.mina.core.filterchain}
write():530, AbstractIoSession {org.apache.mina.core.session}
write():474, AbstractIoSession {org.apache.mina.core.session}
send():51, IoSessionResponder {quickfix.mina}
send():2534, Session {quickfix}
sendRaw():2466, Session {quickfix}
send():2519, Session {quickfix}
sendToTarget():635, Session {quickfix}
sendMessageToTarget():529, FixApplication {de.digitec.d3.gateway.fix}
subscribe():52, FixProducerHandle {de.digitec.d3.gateway.fix}
subscribe():134, FixApplication {de.digitec.d3.gateway.fix}
processMessage():288, FixMessageProcessor {de.digitec.d3.gateway.fix}
run():245, FixMessageProcessor {de.digitec.d3.gateway.fix}
run():878, FixApplication$MessageProcessorThread {de.digitec.d3.gateway.fix}






DIGITEC GmbH
Johannes-Brahms-Platz 1
20355 Hamburg

Tel +49 40 23776-147
Fax +49 40 23776-200
www.DIGITEC.de

___

DIGITEC GmbH EDV-Beratung, Soft- und Hardware
Sitz Hamburg  -  HRB 288 18 Amtsgericht Hamburg
Geschäftsführer: Hans-Joachim Hänel, Hans-Jürgen Joost
Finanzamt Hamburg-Mitte, Steuer-Nr. 48/715/01586  -  VAT-Nr. DE 118646977
WICHTIGER HINWEIS
Die Kommunikation mit DIGITEC GmbH per Email dient nur dem Zweck der schnellen 
Information.
Rechtsverbindliche Absprachen kommen über dieses Medium nicht zustande !
IMPORTANT NOTICE
Communication with digitec GmbH via email is for quick information purposes 
only.
This medium is not to be used for the exchange of legally binding statements !