1 /*
   2  * Copyright (c) 2013, 2018, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.  Oracle designates this
   8  * particular file as subject to the "Classpath" exception as provided
   9  * by Oracle in the LICENSE file that accompanied this code.
  10  *
  11  * This code is distributed in the hope that it will be useful, but WITHOUT
  12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  14  * version 2 for more details (a copy is included in the LICENSE file that
  15  * accompanied this code).
  16  *
  17  * You should have received a copy of the GNU General Public License version
  18  * 2 along with this work; if not, write to the Free Software Foundation,
  19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
  20  *
  21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
  22  * or visit www.oracle.com if you need additional information or have any
  23  * questions.
  24  */
  25 
  26 package jdk.jfr.internal.instrument;
  27 
  28 import java.io.IOException;
  29 import java.net.InetSocketAddress;
  30 import java.nio.ByteBuffer;
  31 
  32 import jdk.jfr.events.SocketReadEvent;
  33 import jdk.jfr.events.SocketWriteEvent;
  34 
  35 /**
  36  * See {@link JITracer} for an explanation of this code.
  37  */
  38 @JIInstrumentationTarget("sun.nio.ch.SocketChannelImpl")
  39 final class SocketChannelImplInstrumentor {
  40 
  41     private SocketChannelImplInstrumentor() {
  42     }
  43 
  44     private InetSocketAddress remoteAddress;
  45 
  46     @SuppressWarnings("deprecation")
  47     @JIInstrumentationMethod
  48     public int read(ByteBuffer dst) throws IOException {
  49         SocketReadEvent event = SocketReadEvent.EVENT.get();
  50         if (!event.isEnabled()) {
  51             return read(dst);
  52         }
  53         int bytesRead = 0;
  54         try {
  55             event.begin();
  56             bytesRead = read(dst);
  57         } finally {
  58             event.end();
  59             if (event.shouldCommit())  {
  60                 String hostString  = remoteAddress.getAddress().toString();
  61                 int delimiterIndex = hostString.lastIndexOf('/');
  62 
  63                 event.host      = hostString.substring(0, delimiterIndex);
  64                 event.address   = hostString.substring(delimiterIndex + 1);
  65                 event.port      = remoteAddress.getPort();
  66                 if (bytesRead < 0) {
  67                     event.endOfStream = true;
  68                 } else {
  69                     event.bytesRead = bytesRead;
  70                 }
  71                 event.timeout   = 0;
  72 
  73                 event.commit();
  74                 event.reset();
  75             }
  76         }
  77         return bytesRead;
  78     }
  79 
  80     @SuppressWarnings("deprecation")
  81     @JIInstrumentationMethod
  82     public long read(ByteBuffer[] dsts, int offset, int length) throws IOException {
  83         SocketReadEvent event = SocketReadEvent.EVENT.get();
  84         if(!event.isEnabled()) {
  85             return read(dsts, offset, length);
  86         }
  87 
  88         long bytesRead = 0;
  89         try {
  90             event.begin();
  91             bytesRead = read(dsts, offset, length);
  92         } finally {
  93             event.end();
  94             if (event.shouldCommit()) {
  95                 String hostString  = remoteAddress.getAddress().toString();
  96                 int delimiterIndex = hostString.lastIndexOf('/');
  97 
  98                 event.host      = hostString.substring(0, delimiterIndex);
  99                 event.address   = hostString.substring(delimiterIndex + 1);
 100                 event.port      = remoteAddress.getPort();
 101                 if (bytesRead < 0) {
 102                     event.endOfStream = true;
 103                 } else {
 104                     event.bytesRead = bytesRead;
 105                 }
 106                 event.timeout   = 0;
 107 
 108                 event.commit();
 109                 event.reset();
 110             }
 111         }
 112         return bytesRead;
 113     }
 114 
 115     @SuppressWarnings("deprecation")
 116     @JIInstrumentationMethod
 117     public int write(ByteBuffer buf) throws IOException {
 118         SocketWriteEvent event = SocketWriteEvent.EVENT.get();
 119         if (!event.isEnabled()) {
 120             return write(buf);
 121         }
 122 
 123         int bytesWritten = 0;
 124         try {
 125             event.begin();
 126             bytesWritten = write(buf);
 127         } finally {
 128             event.end();
 129             if (event.shouldCommit()) {
 130                 String hostString  = remoteAddress.getAddress().toString();
 131                 int delimiterIndex = hostString.lastIndexOf('/');
 132 
 133                 event.host         = hostString.substring(0, delimiterIndex);
 134                 event.address      = hostString.substring(delimiterIndex + 1);
 135                 event.port         = remoteAddress.getPort();
 136                 event.bytesWritten = bytesWritten < 0 ? 0 : bytesWritten;
 137 
 138                 event.commit();
 139                 event.reset();
 140             }
 141         }
 142         return bytesWritten;
 143     }
 144 
 145     @SuppressWarnings("deprecation")
 146     @JIInstrumentationMethod
 147     public long write(ByteBuffer[] srcs, int offset, int length) throws IOException {
 148         SocketWriteEvent event = SocketWriteEvent.EVENT.get();
 149         if (!event.isEnabled()) {
 150             return write(srcs, offset, length);
 151         }
 152         long bytesWritten = 0;
 153         try {
 154             event.begin();
 155             bytesWritten = write(srcs, offset, length);
 156         } finally {
 157             event.end();
 158             if (event.shouldCommit()) {
 159                 String hostString  = remoteAddress.getAddress().toString();
 160                 int delimiterIndex = hostString.lastIndexOf('/');
 161 
 162                 event.host         = hostString.substring(0, delimiterIndex);
 163                 event.address      = hostString.substring(delimiterIndex + 1);
 164                 event.port         = remoteAddress.getPort();
 165                 event.bytesWritten = bytesWritten < 0 ? 0 : bytesWritten;
 166 
 167                 event.commit();
 168                 event.reset();
 169             }
 170         }
 171         return bytesWritten;
 172     }
 173 
 174 }